@@ -376,6 +376,14 @@ var makeKey = function(path) {
376
376
} ;
377
377
378
378
379
+ var resolve = function ( reference , context ) {
380
+ if ( ! reference . match ( / ^ # ( \/ ( [ a - z A - Z _ ] [ a - z A - 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
+
379
387
var makeFields = function ( props ) {
380
388
var hints = ou . getIn ( props , [ 'schema' , 'x-hints' ] ) || { } ;
381
389
var inputComponent = ou . getIn ( hints , [ 'form' , 'inputComponent' ] ) ;
@@ -392,6 +400,10 @@ var makeFields = function(props) {
392
400
return wrappedField ( props , UserDefinedField ( props ) ) ;
393
401
} else if ( hints . fileUpload )
394
402
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
+ } ) ) ;
395
407
else if ( props . schema [ 'oneOf' ] )
396
408
return wrappedSection ( props , fieldsForAlternative ( props ) ) ;
397
409
else if ( props . schema [ 'enum' ] ) {
@@ -415,24 +427,30 @@ var makeFields = function(props) {
415
427
} ;
416
428
417
429
418
- var withDefaultOptions = function ( data , schema ) {
430
+ var withDefaultOptions = function ( data , schema , context ) {
419
431
var result ;
420
432
var key ;
421
433
422
- if ( schema [ 'enum' ] ) {
434
+ if ( schema [ '$ref' ] ) {
435
+ result = withDefaultOptions ( data , resolve ( schema [ '$ref' ] , context ) , context ) ;
436
+ } else if ( schema [ 'enum' ] ) {
423
437
result = data || schema [ 'enum' ] [ 0 ] ;
424
438
} else if ( schema . oneOf ) {
425
- result = withDefaultOptions ( data , schemaForAlternative ( data , schema ) ) ;
439
+ result = withDefaultOptions ( data ,
440
+ schemaForAlternative ( data , schema , context ) ,
441
+ context ) ;
426
442
} else if ( schema . type == 'object' ) {
427
443
result = ou . merge ( data ) ;
428
444
for ( key in schema . properties )
429
445
result [ key ] = withDefaultOptions ( ( data || { } ) [ key ] ,
430
- schema . properties [ key ] ) ;
446
+ schema . properties [ key ] ,
447
+ context ) ;
431
448
} else if ( schema . type == 'array' ) {
432
449
result = [ ] ;
433
450
for ( key = 0 ; key < ( data || [ ] ) . length ; ++ key )
434
451
result [ key ] = withDefaultOptions ( ( data || [ ] ) [ key ] ,
435
- schema . items ) ;
452
+ schema . items ,
453
+ context ) ;
436
454
} else {
437
455
result = data ;
438
456
}
@@ -451,19 +469,23 @@ var hashedErrors = function(errors) {
451
469
} ;
452
470
453
471
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 ;
456
478
} ;
457
479
458
480
459
481
var Form = React . createClass ( {
460
482
displayName : 'Form' ,
461
483
462
484
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 ,
467
489
errors : errors } ;
468
490
} ,
469
491
componentWillReceiveProps : function ( props ) {
@@ -472,14 +494,17 @@ var Form = React.createClass({
472
494
this . setState ( {
473
495
values : values ,
474
496
output : output ,
475
- errors : hashedErrors ( this . props . validate ( props . schema , output ) )
497
+ errors : this . validate ( props . schema , output , context ( props ) )
476
498
} ) ;
477
499
} ,
478
500
setValue : function ( path , raw , parsed ) {
479
501
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 ) ;
483
508
484
509
if ( this . props . submitOnChange )
485
510
this . props . onSubmit ( output , null , errors ) ;
@@ -496,6 +521,9 @@ var Form = React.createClass({
496
521
getErrors : function ( path ) {
497
522
return this . state . errors [ makeKey ( path ) ] ;
498
523
} ,
524
+ validate : function ( schema , values , context ) {
525
+ return hashedErrors ( this . props . validate ( schema , values , context ) ) ;
526
+ } ,
499
527
preventSubmit : function ( event ) {
500
528
event . preventDefault ( ) ;
501
529
} ,
@@ -512,6 +540,7 @@ var Form = React.createClass({
512
540
var schema = this . props . schema ;
513
541
var fields = makeFields ( {
514
542
schema : this . props . schema ,
543
+ context : context ( this . props ) ,
515
544
fieldWrapper : this . props . fieldWrapper ,
516
545
sectionWrapper : this . props . sectionWrapper ,
517
546
handlers : this . props . handlers ,
0 commit comments