Skip to content

Commit ed4c429

Browse files
committed
Close #5: Add support for referencing and nesting
1 parent efb4306 commit ed4c429

File tree

4 files changed

+120
-58
lines changed

4 files changed

+120
-58
lines changed

src/components/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import Button from './buttons';
22
import {FormInput, FormCheckInput, FormRadioInput, FormSelectInput, FormFileInput,
33
FormTextareaInput, FormDateTimeInput, FormMultiSelectInput} from './form';
4-
import {FormRow, FormGroup, FormRowControls} from './containers';
4+
import {FormRow, FormGroup, FormRowControls, GroupTitle} from './containers';
55
import Loader from './loaders';
66
import Icon from './icons';
77

88
export {
99
Button,
1010
FormInput, FormCheckInput, FormRadioInput, FormSelectInput, FormFileInput,
1111
FormTextareaInput, FormDateTimeInput, FormMultiSelectInput,
12-
FormRow, FormGroup, FormRowControls,
12+
FormRow, FormGroup, FormRowControls, GroupTitle,
1313
Loader,
1414
Icon,
1515
};

src/data.js

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
export function getBlankObject(schema) {
1+
export function getBlankObject(schema, getRef) {
22
let keys = {};
33

44
let schema_keys = schema.keys || schema.properties;
55

66
for (let key in schema_keys) {
77
let value = schema_keys[key];
8+
9+
let isRef = value.hasOwnProperty('$ref');
10+
11+
if (isRef)
12+
value = getRef(value['$ref']);
13+
814
let type = value.type;
915

1016
if (type === 'list')
@@ -13,9 +19,9 @@ export function getBlankObject(schema) {
1319
type = 'object';
1420

1521
if (type === 'array')
16-
keys[key] = getBlankArray(value);
22+
keys[key] = isRef ? [] : getBlankArray(value, getRef);
1723
else if (type === 'object')
18-
keys[key] = getBlankObject(value);
24+
keys[key] = isRef ? {} : getBlankObject(value, getRef);
1925
else if (type === 'boolean')
2026
keys[key] = value.default || false;
2127
else if (type === 'integer' || type === 'number')
@@ -28,11 +34,17 @@ export function getBlankObject(schema) {
2834
}
2935

3036

31-
export function getBlankArray(schema) {
37+
export function getBlankArray(schema, getRef) {
3238
if (schema.default)
3339
return schema.default;
3440

3541
let items = [];
42+
if (schema.items.hasOwnProperty('$ref')) {
43+
// :TODO: this will most probably mutate the original schema
44+
// but i'll fix it later
45+
schema.items = getRef(schema.items['$ref'])
46+
}
47+
3648
let type = schema.items.type;
3749

3850
if (type === 'list')
@@ -41,11 +53,11 @@ export function getBlankArray(schema) {
4153
type = 'object';
4254

4355
if (type === 'array') {
44-
items.push(getBlankArray(schema.items))
56+
items.push(getBlankArray(schema.items, getRef))
4557
return items;
4658
}
4759
else if (type === 'object') {
48-
items.push(getBlankObject(schema.items));
60+
items.push(getBlankObject(schema.items, getRef));
4961
return items;
5062
}
5163

@@ -63,7 +75,10 @@ export function getBlankArray(schema) {
6375
}
6476

6577

66-
export function getBlankData(schema) {
78+
export function getBlankData(schema, getRef) {
79+
if (schema.hasOwnProperty('$ref'))
80+
schema = getRef(schema['$ref']);
81+
6782
let type = schema.type;
6883

6984
if (type === 'list')
@@ -72,9 +87,9 @@ export function getBlankData(schema) {
7287
type = 'object';
7388

7489
if (type === 'array')
75-
return getBlankArray(schema);
90+
return getBlankArray(schema, getRef);
7691
else if (type === 'object')
77-
return getBlankObject(schema);
92+
return getBlankObject(schema, getRef);
7893
else if (type === 'boolean')
7994
return schema.default || false;
8095
else if (type === 'integer' || type === 'number')
@@ -85,9 +100,15 @@ export function getBlankData(schema) {
85100

86101

87102

88-
function getSyncedArray(data, schema) {
103+
function getSyncedArray(data, schema, getRef) {
89104
let newData = JSON.parse(JSON.stringify(data));
90105

106+
if (schema.items.hasOwnProperty('$ref')) {
107+
// :TODO: this will most probably mutate the original schema
108+
// but i'll fix it later
109+
schema.items = getRef(schema.items['$ref'])
110+
}
111+
91112
let type = schema.items.type;
92113

93114
if (type === 'list')
@@ -99,9 +120,9 @@ function getSyncedArray(data, schema) {
99120
let item = data[i];
100121

101122
if (type === 'array') {
102-
newData[i] = getSyncedArray(item, schema.items);
123+
newData[i] = getSyncedArray(item, schema.items, getRef);
103124
} else if (type === 'object') {
104-
newData[i] = getSyncedObject(item, schema.items);
125+
newData[i] = getSyncedObject(item, schema.items, getRef);
105126
}
106127
else {
107128
if ((type === 'integer' || type === 'number') && item === '')
@@ -113,7 +134,7 @@ function getSyncedArray(data, schema) {
113134
}
114135

115136

116-
function getSyncedObject(data, schema) {
137+
function getSyncedObject(data, schema, getRef) {
117138
let newData = JSON.parse(JSON.stringify(data));
118139

119140
let schema_keys = schema.keys || schema.properties;
@@ -123,6 +144,12 @@ function getSyncedObject(data, schema) {
123144
for (let i = 0; i < keys.length; i++) {
124145
let key = keys[i];
125146
let schemaValue = schema_keys[key];
147+
148+
let isRef = schemaValue.hasOwnProperty('$ref');
149+
150+
if (isRef)
151+
schemaValue = getRef(schemaValue['$ref']);
152+
126153
let type = schemaValue.type;
127154

128155
if (type === 'list')
@@ -132,9 +159,9 @@ function getSyncedObject(data, schema) {
132159

133160
if (!data.hasOwnProperty(key)) {
134161
if (type === 'array')
135-
newData[key] = getSyncedArray([], schemaValue);
162+
newData[key] = getSyncedArray([], schemaValue, getRef);
136163
else if (type === 'object')
137-
newData[key] = getSyncedObject({}, schemaValue);
164+
newData[key] = getSyncedObject({}, schemaValue, getRef);
138165
else if (type === 'boolean')
139166
newData[key] = false;
140167
else if (type === 'integer' || type === 'number')
@@ -143,9 +170,9 @@ function getSyncedObject(data, schema) {
143170
newData[key] = '';
144171
} else {
145172
if (type === 'array')
146-
newData[key] = getSyncedArray(data[key], schemaValue);
173+
newData[key] = getSyncedArray(data[key], schemaValue, getRef);
147174
else if (type === 'object')
148-
newData[key] = getSyncedObject(data[key], schemaValue);
175+
newData[key] = getSyncedObject(data[key], schemaValue, getRef);
149176
else {
150177
if ((type === 'integer' || type === 'number') && data[key] === '')
151178
newData[key] = null;
@@ -160,9 +187,12 @@ function getSyncedObject(data, schema) {
160187
}
161188

162189

163-
export function getSyncedData(data, schema) {
190+
export function getSyncedData(data, schema, getRef) {
164191
// adds those keys to data which are in schema but not in data
165192

193+
if (schema.hasOwnProperty('$ref'))
194+
schema = getRef(schema['$ref']);
195+
166196
let type = schema.type;
167197

168198
if (type === 'list')
@@ -171,9 +201,9 @@ export function getSyncedData(data, schema) {
171201
type = 'object';
172202

173203
if (type === 'array') {
174-
return getSyncedArray(data, schema);
204+
return getSyncedArray(data, schema, getRef);
175205
} else if (type === 'object') {
176-
return getSyncedObject(data, schema);
206+
return getSyncedObject(data, schema, getRef);
177207
}
178208

179209
return data;

src/form.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ export default class Form extends React.Component {
1414

1515
if (!data) {
1616
// create empty data from schema
17-
data = getBlankData(this.schema);
17+
data = getBlankData(this.schema, this.getRef);
1818
} else {
1919
// data might be stale if schema has new keys, so add them to data
2020
try {
21-
data = getSyncedData(data, this.schema);
21+
data = getSyncedData(data, this.schema, this.getRef);
2222
} catch (error) {
2323
console.error("Error: Schema and data structure don't match");
2424
console.error(error);
@@ -76,6 +76,25 @@ export default class Form extends React.Component {
7676
this.setState({data: _data});
7777
}
7878

79+
getRef = (ref) => {
80+
/* Returns schema reference. Nothing to do with React's refs.*/
81+
82+
let refSchema;
83+
let tokens = ref.split('/');
84+
85+
for (let i = 0; i < tokens.length; i++) {
86+
let token = tokens[i];
87+
88+
if (token === '#')
89+
refSchema = this.schema;
90+
else
91+
refSchema = refSchema[token];
92+
}
93+
94+
95+
return {...refSchema};
96+
}
97+
7998
getFields = () => {
8099
let data = this.state.data;
81100
let formGroups = [];
@@ -96,7 +115,8 @@ export default class Form extends React.Component {
96115
onAdd: this.addFieldset,
97116
onRemove: this.removeFieldset,
98117
onMove: this.moveFieldset,
99-
level: 0
118+
level: 0,
119+
getRef: this.getRef,
100120
};
101121

102122
if (type === 'array') {

0 commit comments

Comments
 (0)