@@ -56,30 +56,27 @@ Formsy.Form = React.createClass({
56
56
detachFromForm : this . detachFromForm ,
57
57
validate : this . validate ,
58
58
isFormDisabled : this . isFormDisabled ,
59
- isValidValue : function ( component , value ) {
59
+ isValidValue : ( component , value ) => {
60
60
return this . runValidation ( component , value ) . isValid ;
61
- } . bind ( this )
61
+ }
62
62
}
63
63
}
64
64
} ,
65
65
66
66
// Add a map to store the inputs of the form, a model to store
67
67
// the values of the form and register child inputs
68
68
componentWillMount : function ( ) {
69
- this . inputs = { } ;
70
- this . model = { } ;
69
+ this . inputs = [ ] ;
71
70
} ,
72
71
73
72
componentDidMount : function ( ) {
74
73
this . validateForm ( ) ;
75
74
} ,
76
75
77
76
componentWillUpdate : function ( ) {
78
-
79
- // Keep a reference to input keys before form updates,
77
+ // Keep a reference to input names before form updates,
80
78
// to check if inputs has changed after render
81
- this . prevInputKeys = Object . keys ( this . inputs ) ;
82
-
79
+ this . prevInputNames = this . inputs . map ( component => component . props . name ) ;
83
80
} ,
84
81
85
82
componentDidUpdate : function ( ) {
@@ -88,8 +85,8 @@ Formsy.Form = React.createClass({
88
85
this . setInputValidationErrors ( this . props . validationErrors ) ;
89
86
}
90
87
91
- var newInputKeys = Object . keys ( this . inputs ) ;
92
- if ( utils . arraysDiffer ( this . prevInputKeys , newInputKeys ) ) {
88
+ var newInputNames = this . inputs . map ( component => component . props . name ) ;
89
+ if ( utils . arraysDiffer ( this . prevInputNames , newInputNames ) ) {
93
90
this . validateForm ( ) ;
94
91
}
95
92
@@ -110,62 +107,65 @@ Formsy.Form = React.createClass({
110
107
// If any inputs have not been touched yet this will make them dirty
111
108
// so validation becomes visible (if based on isPristine)
112
109
this . setFormPristine ( false ) ;
113
- this . updateModel ( ) ;
114
- var model = this . mapModel ( ) ;
110
+ var model = this . getModel ( ) ;
111
+ model = this . mapModel ( model ) ;
115
112
this . props . onSubmit ( model , this . resetModel , this . updateInputsWithError ) ;
116
113
this . state . isValid ? this . props . onValidSubmit ( model , this . resetModel , this . updateInputsWithError ) : this . props . onInvalidSubmit ( model , this . resetModel , this . updateInputsWithError ) ;
117
114
118
115
} ,
119
116
120
- mapModel : function ( ) {
117
+ mapModel : function ( model ) {
118
+
121
119
if ( this . props . mapping ) {
122
- return this . props . mapping ( this . model )
120
+ return this . props . mapping ( model )
123
121
} else {
124
- return formDataToObject ( Object . keys ( this . model ) . reduce ( function ( mappedModel , key ) {
122
+ return formDataToObject ( Object . keys ( model ) . reduce ( ( mappedModel , key ) => {
125
123
126
124
var keyArray = key . split ( '.' ) ;
127
125
var base = mappedModel ;
128
126
while ( keyArray . length ) {
129
127
var currentKey = keyArray . shift ( ) ;
130
- base = ( base [ currentKey ] = keyArray . length ? base [ currentKey ] || { } : this . model [ key ] ) ;
128
+ base = ( base [ currentKey ] = keyArray . length ? base [ currentKey ] || { } : model [ key ] ) ;
131
129
}
132
130
133
131
return mappedModel ;
134
132
135
- } . bind ( this ) , { } ) ) ;
133
+ } , { } ) ) ;
136
134
}
137
135
} ,
138
136
139
137
// Goes through all registered components and
140
138
// updates the model values
141
- updateModel : function ( ) {
142
- Object . keys ( this . inputs ) . forEach ( function ( name ) {
143
- var component = this . inputs [ name ] ;
144
- this . model [ name ] = component . state . _value ;
145
- } . bind ( this ) ) ;
139
+ getModel : function ( ) {
140
+ return this . inputs . reduce ( ( model , component ) => {
141
+ var name = component . props . name ;
142
+ model [ name ] = component . state . _value ;
143
+ return model ;
144
+ } , { } ) ;
146
145
} ,
147
146
148
147
// Reset each key in the model to the original / initial / specified value
149
148
resetModel : function ( data ) {
150
- Object . keys ( this . inputs ) . forEach ( function ( name ) {
149
+ this . inputs . forEach ( component => {
150
+ var name = component . props . name ;
151
151
if ( data && data [ name ] ) {
152
- this . inputs [ name ] . setValue ( data [ name ] ) ;
152
+ component . setValue ( data [ name ] ) ;
153
153
} else {
154
- this . inputs [ name ] . resetValue ( ) ;
154
+ component . resetValue ( ) ;
155
155
}
156
- } . bind ( this ) ) ;
156
+ } ) ;
157
157
this . validateForm ( ) ;
158
158
} ,
159
159
160
160
setInputValidationErrors : function ( errors ) {
161
- Object . keys ( this . inputs ) . forEach ( function ( name , index ) {
162
- var component = this . inputs [ name ] ;
161
+ this . inputs . forEach ( component => {
162
+ var name = component . props . name ;
163
163
var args = [ {
164
164
_isValid : ! ( name in errors ) ,
165
165
_validationError : typeof errors [ name ] === 'string' ? [ errors [ name ] ] : errors [ name ]
166
166
} ] ;
167
167
component . setState . apply ( component , args ) ;
168
- } . bind ( this ) ) ;
168
+ } ) ;
169
169
} ,
170
170
171
171
// Checks if the values have changed from their initial value
@@ -174,9 +174,8 @@ Formsy.Form = React.createClass({
174
174
} ,
175
175
176
176
getPristineValues : function ( ) {
177
- var inputs = this . inputs ;
178
- return Object . keys ( inputs ) . reduce ( function ( data , name ) {
179
- var component = inputs [ name ] ;
177
+ return this . inputs . reduce ( ( data , component ) => {
178
+ var name = component . props . name ;
180
179
data [ name ] = component . props . value ;
181
180
return data ;
182
181
} , { } ) ;
@@ -186,49 +185,45 @@ Formsy.Form = React.createClass({
186
185
// stored in the inputs map. Change their state to invalid
187
186
// and set the serverError message
188
187
updateInputsWithError : function ( errors ) {
189
- Object . keys ( errors ) . forEach ( function ( name , index ) {
190
- var component = this . inputs [ name ] ;
191
-
188
+ Object . keys ( errors ) . forEach ( ( name , index ) => {
189
+ var component = utils . find ( this . inputs , component => component . props . name === name ) ;
192
190
if ( ! component ) {
193
- throw new Error ( 'You are trying to update an input that does not exist. Verify errors object with input names. ' + JSON . stringify ( errors ) ) ;
191
+ throw new Error ( 'You are trying to update an input that does not exist. ' +
192
+ 'Verify errors object with input names. ' + JSON . stringify ( errors ) ) ;
194
193
}
195
194
var args = [ {
196
195
_isValid : this . props . preventExternalInvalidation || false ,
197
196
_externalError : typeof errors [ name ] === 'string' ? [ errors [ name ] ] : errors [ name ]
198
197
} ] ;
199
198
component . setState . apply ( component , args ) ;
200
- } . bind ( this ) ) ;
199
+ } ) ;
201
200
} ,
202
201
203
202
isFormDisabled : function ( ) {
204
203
return this . props . disabled ;
205
204
} ,
206
205
207
206
getCurrentValues : function ( ) {
208
- return Object . keys ( this . inputs ) . reduce ( function ( data , name ) {
209
- var component = this . inputs [ name ] ;
207
+ return this . inputs . reduce ( ( data , component ) => {
208
+ var name = component . props . name ;
210
209
data [ name ] = component . state . _value ;
211
210
return data ;
212
- } . bind ( this ) , { } ) ;
211
+ } , { } ) ;
213
212
} ,
214
213
215
214
setFormPristine : function ( isPristine ) {
216
- var inputs = this . inputs ;
217
- var inputKeys = Object . keys ( inputs ) ;
218
-
219
215
this . setState ( {
220
- _formSubmitted : ! isPristine
221
- } )
216
+ _formSubmitted : ! isPristine
217
+ } ) ;
222
218
223
219
// Iterate through each component and set it as pristine
224
220
// or "dirty".
225
- inputKeys . forEach ( function ( name , index ) {
226
- var component = inputs [ name ] ;
221
+ this . inputs . forEach ( ( component , index ) => {
227
222
component . setState ( {
228
223
_formSubmitted : ! isPristine ,
229
224
_isPristine : isPristine
230
225
} ) ;
231
- } . bind ( this ) ) ;
226
+ } ) ;
232
227
} ,
233
228
234
229
// Use the binded values and the actual input value to
@@ -362,16 +357,13 @@ Formsy.Form = React.createClass({
362
357
// Validate the form by going through all child input components
363
358
// and check their state
364
359
validateForm : function ( ) {
365
- var allIsValid ;
366
- var inputs = this . inputs ;
367
- var inputKeys = Object . keys ( inputs ) ;
368
360
369
361
// We need a callback as we are validating all inputs again. This will
370
362
// run when the last component has set its state
371
363
var onValidationComplete = function ( ) {
372
- allIsValid = inputKeys . every ( function ( name ) {
373
- return inputs [ name ] . state . _isValid ;
374
- } . bind ( this ) ) ;
364
+ var allIsValid = this . inputs . every ( component => {
365
+ return component . state . _isValid ;
366
+ } ) ;
375
367
376
368
this . setState ( {
377
369
isValid : allIsValid
@@ -392,8 +384,7 @@ Formsy.Form = React.createClass({
392
384
393
385
// Run validation again in case affected by other inputs. The
394
386
// last component validated will run the onValidationComplete callback
395
- inputKeys . forEach ( function ( name , index ) {
396
- var component = inputs [ name ] ;
387
+ this . inputs . forEach ( ( component , index ) => {
397
388
var validation = this . runValidation ( component ) ;
398
389
if ( validation . isValid && component . state . _externalError ) {
399
390
validation . isValid = false ;
@@ -403,12 +394,12 @@ Formsy.Form = React.createClass({
403
394
_isRequired : validation . isRequired ,
404
395
_validationError : validation . error ,
405
396
_externalError : ! validation . isValid && component . state . _externalError ? component . state . _externalError : null
406
- } , index === inputKeys . length - 1 ? onValidationComplete : null ) ;
407
- } . bind ( this ) ) ;
397
+ } , index === this . inputs . length - 1 ? onValidationComplete : null ) ;
398
+ } ) ;
408
399
409
400
// If there are no inputs, set state where form is ready to trigger
410
401
// change event. New inputs might be added later
411
- if ( ! inputKeys . length && this . isMounted ( ) ) {
402
+ if ( ! this . inputs . length && this . isMounted ( ) ) {
412
403
this . setState ( {
413
404
canChange : true
414
405
} ) ;
@@ -418,16 +409,24 @@ Formsy.Form = React.createClass({
418
409
// Method put on each input component to register
419
410
// itself to the form
420
411
attachToForm : function ( component ) {
421
- this . inputs [ component . props . name ] = component ;
422
- this . model [ component . props . name ] = component . state . _value ;
412
+
413
+ if ( this . inputs . indexOf ( component ) === - 1 ) {
414
+ this . inputs . push ( component ) ;
415
+ }
416
+
423
417
this . validate ( component ) ;
424
418
} ,
425
419
426
420
// Method put on each input component to unregister
427
421
// itself from the form
428
422
detachFromForm : function ( component ) {
429
- delete this . inputs [ component . props . name ] ;
430
- delete this . model [ component . props . name ] ;
423
+ var componentPos = this . inputs . indexOf ( component ) ;
424
+
425
+ if ( componentPos !== - 1 ) {
426
+ this . inputs = this . inputs . slice ( 0 , componentPos )
427
+ . concat ( this . inputs . slice ( componentPos + 1 ) ) ;
428
+ }
429
+
431
430
this . validateForm ( ) ;
432
431
} ,
433
432
render : function ( ) {
0 commit comments