Skip to content

Commit 0f4c0cc

Browse files
committed
add support for (local only) subschema references
1 parent 687cba3 commit 0f4c0cc

File tree

4 files changed

+196
-51
lines changed

4 files changed

+196
-51
lines changed

dist/src/app.js

+134-31
Large diffs are not rendered by default.

example/app.jsx

+17-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ window.React = React;
99

1010

1111
var schema = {
12+
definitions: {
13+
weight: {
14+
title: "Weight",
15+
type: "object",
16+
properties: {
17+
amount: {
18+
type: "number",
19+
minimum: 0,
20+
exclusiveMinimum: true
21+
},
22+
unit: {
23+
enum: [ "kg", "lbs" ]
24+
}
25+
}
26+
}
27+
},
1228
title: "Example form",
1329
description: "A form based on a schema",
1430
type: "object",
@@ -33,10 +49,7 @@ var schema = {
3349
minimum: 1
3450
},
3551
weight: {
36-
title: "Your weight in kg",
37-
type: "number",
38-
minimum: 0,
39-
exclusiveMinimum: true
52+
"$ref": "#/definitions/weight"
4053
},
4154
color: {
4255
title: "Favourite colour",

index.js

+44-15
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,14 @@ var makeKey = function(path) {
376376
};
377377

378378

379+
var resolve = function(reference, context) {
380+
if (!reference.match(/^#(\/([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+))*$/))
381+
throw new Error('reference '+reference+' has unsupported format');
382+
383+
return ou.getIn(context, reference.split('/').slice(1));
384+
};
385+
386+
379387
var makeFields = function(props) {
380388
var hints = ou.getIn(props, ['schema', 'x-hints']) || {};
381389
var inputComponent = ou.getIn(hints, ['form', 'inputComponent']);
@@ -392,6 +400,10 @@ var makeFields = function(props) {
392400
return wrappedField(props, UserDefinedField(props));
393401
} else if (hints.fileUpload)
394402
return FileField(ou.merge(props, { mode: hints.fileUpload.mode }));
403+
else if (props.schema['$ref'])
404+
return makeFields(ou.merge(props, {
405+
schema: resolve(props.schema['$ref'], props.context)
406+
}));
395407
else if (props.schema['oneOf'])
396408
return wrappedSection(props, fieldsForAlternative(props));
397409
else if (props.schema['enum']) {
@@ -415,24 +427,30 @@ var makeFields = function(props) {
415427
};
416428

417429

418-
var withDefaultOptions = function(data, schema) {
430+
var withDefaultOptions = function(data, schema, context) {
419431
var result;
420432
var key;
421433

422-
if (schema['enum']) {
434+
if (schema['$ref']) {
435+
result = withDefaultOptions(data, resolve(schema['$ref'], context), context);
436+
} else if (schema['enum']) {
423437
result = data || schema['enum'][0];
424438
} else if (schema.oneOf) {
425-
result = withDefaultOptions(data, schemaForAlternative(data, schema));
439+
result = withDefaultOptions(data,
440+
schemaForAlternative(data, schema, context),
441+
context);
426442
} else if (schema.type == 'object') {
427443
result = ou.merge(data);
428444
for (key in schema.properties)
429445
result[key] = withDefaultOptions((data || {})[key],
430-
schema.properties[key]);
446+
schema.properties[key],
447+
context);
431448
} else if (schema.type == 'array') {
432449
result = [];
433450
for (key = 0; key < (data || []).length; ++key)
434451
result[key] = withDefaultOptions((data || [])[key],
435-
schema.items);
452+
schema.items,
453+
context);
436454
} else {
437455
result = data;
438456
}
@@ -451,19 +469,23 @@ var hashedErrors = function(errors) {
451469
};
452470

453471

454-
var normalise = function(data, schema) {
455-
return ou.prune(withDefaultOptions(data, schema));
472+
var normalise = function(data, schema, context) {
473+
return ou.prune(withDefaultOptions(data, schema, context));
474+
};
475+
476+
var context = function(props) {
477+
return props.context || props.schema;
456478
};
457479

458480

459481
var Form = React.createClass({
460482
displayName: 'Form',
461483

462484
getInitialState: function() {
463-
var errors =
464-
hashedErrors(this.props.validate(this.props.schema, this.props.values));
465-
return { values: this.props.values,
466-
output: this.props.values,
485+
var values = this.props.values;
486+
var errors = this.validate(this.props.schema, values, context(this.props));
487+
return { values: values,
488+
output: values,
467489
errors: errors };
468490
},
469491
componentWillReceiveProps: function(props) {
@@ -472,14 +494,17 @@ var Form = React.createClass({
472494
this.setState({
473495
values: values,
474496
output: output,
475-
errors: hashedErrors(this.props.validate(props.schema, output))
497+
errors: this.validate(props.schema, output, context(props))
476498
});
477499
},
478500
setValue: function(path, raw, parsed) {
479501
var schema = this.props.schema;
480-
var values = normalise(ou.setIn(this.state.values, path, raw), schema);
481-
var output = normalise(ou.setIn(this.state.output, path, parsed), schema);
482-
var errors = hashedErrors(this.props.validate(schema, output));
502+
var ctx = context(this.props);
503+
var values = normalise(ou.setIn(this.state.values, path, raw),
504+
schema, ctx);
505+
var output = normalise(ou.setIn(this.state.output, path, parsed),
506+
schema, ctx);
507+
var errors = this.validate(schema, output, ctx);
483508

484509
if (this.props.submitOnChange)
485510
this.props.onSubmit(output, null, errors);
@@ -496,6 +521,9 @@ var Form = React.createClass({
496521
getErrors: function(path) {
497522
return this.state.errors[makeKey(path)];
498523
},
524+
validate: function(schema, values, context) {
525+
return hashedErrors(this.props.validate(schema, values, context));
526+
},
499527
preventSubmit: function(event) {
500528
event.preventDefault();
501529
},
@@ -512,6 +540,7 @@ var Form = React.createClass({
512540
var schema = this.props.schema;
513541
var fields = makeFields({
514542
schema : this.props.schema,
543+
context : context(this.props),
515544
fieldWrapper : this.props.fieldWrapper,
516545
sectionWrapper: this.props.sectionWrapper,
517546
handlers : this.props.handlers,

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"browserify": "^4.1.11",
2727
"gulp": "^3.8.2",
2828
"gulp-rename": "^1.2.0",
29-
"plexus-validate": "~0.0.2",
29+
"plexus-validate": "~0.0.3",
3030
"reactify": "^0.13.1",
3131
"vinyl-source-stream": "^0.1.1"
3232
},

0 commit comments

Comments
 (0)