@@ -2,7 +2,8 @@ import * as React from 'react';
22import { pipe , isNil } from './utils' ;
33
44import * as validation from './validate' ;
5- import { IFormConfig , IBoundInput } from './interfaces' ;
5+ import { IFormConfig , IBoundInput , IFormProps } from './interfaces' ;
6+ import { ReactElement } from 'react' ;
67
78const hoistNonReactStatics = require ( 'hoist-non-react-statics' ) ;
89
@@ -13,7 +14,8 @@ const makeWrapper = <T extends {}>(config: IFormConfig<T>) => (WrappedComponent:
1314 this . state = {
1415 model : config . initialModel || { } ,
1516 touched : { } ,
16- inputs : { }
17+ inputs : { } ,
18+ shouldValidate : { }
1719 } ;
1820 }
1921
@@ -33,6 +35,12 @@ const makeWrapper = <T extends {}>(config: IFormConfig<T>) => (WrappedComponent:
3335 setFieldToTouched = ( prop : keyof T ) =>
3436 this . setTouched ( Object . assign ( { } , this . state . touched , { [ prop ] : true } ) ) ;
3537
38+ setShouldValidate = ( prop : keyof T , isSet : boolean = true ) => {
39+ const shouldValidate = Object . assign ( { } , this . state . shouldValidate , { [ prop ] : isSet } ) ;
40+ this . setState ( { shouldValidate } ) ;
41+ return shouldValidate ;
42+ } ;
43+
3644 getValue = ( name : keyof T ) => {
3745 const { state : { model : { [ name ] : modelValue } } } = this ;
3846
@@ -97,15 +105,17 @@ const makeWrapper = <T extends {}>(config: IFormConfig<T>) => (WrappedComponent:
97105 form : {
98106 model : this . state . model ,
99107 inputs : this . state . inputs ,
100- touched : this . state . touched
108+ touched : this . state . touched ,
109+ shouldValidate : this . state . shouldValidate
101110 } ,
102111 formMethods : {
103112 bindInput : this . bindInput ,
104113 bindNativeInput : this . bindNativeInput ,
105114 bindToChangeEvent : this . bindToChangeEvent ,
106115 setProperty : this . setProperty ,
107116 setModel : this . setModel ,
108- setFieldToTouched : this . setFieldToTouched
117+ setFieldToTouched : this . setFieldToTouched ,
118+ setShouldValidate : this . setShouldValidate
109119 }
110120 } ) ;
111121
@@ -122,3 +132,35 @@ export const connectForm = <T extends {} = any>(
122132 validators : any [ ] = [ ] ,
123133 config : IFormConfig < T > = { }
124134) => ( Component : any ) => pipe ( validation . validate ( validators ) , makeWrapper < T > ( config ) ) ( Component ) ;
135+
136+ export interface IControlProps extends IFormProps {
137+ name : string ;
138+ render ?: ( ...args : any [ ] ) => any ;
139+ shouldValidate ?: boolean ;
140+ }
141+
142+ export class Control extends React . Component < IControlProps , { } > {
143+ componentDidMount ( ) {
144+ this . setShouldValidate ( ) ;
145+ }
146+
147+ componentWillReceiveProps ( nextProps : IControlProps ) {
148+ if ( nextProps . shouldValidate !== this . props . shouldValidate ) {
149+ this . setShouldValidate ( ) ;
150+ }
151+ }
152+
153+ private setShouldValidate ( ) {
154+ const { shouldValidate, formMethods } = this . props ;
155+ if ( shouldValidate !== undefined ) {
156+ formMethods . setShouldValidate ( this . props . name , shouldValidate ) ;
157+ }
158+ }
159+
160+ render ( ) {
161+ const { name, formMethods : { bindInput } } = this . props ;
162+ return React . Children . map ( this . props . children , child =>
163+ React . cloneElement ( child as ReactElement < any > , { ...bindInput ( name ) } )
164+ ) ;
165+ }
166+ }
0 commit comments