@@ -8,7 +8,10 @@ import warning from '../_util/warning';
8
8
import FormItem from './FormItem' ;
9
9
import { initDefaultProps , getSlot } from '../_util/props-util' ;
10
10
import { ConfigConsumerProps } from '../config-provider' ;
11
- import { getParams } from './utils' ;
11
+ import { getNamePath , containsNamePath } from './utils/valueUtil' ;
12
+ import { defaultValidateMessages } from './utils/messages' ;
13
+ import { allPromiseFinish } from './utils/asyncUtil' ;
14
+ import { toArray } from './utils/typeUtil' ;
12
15
13
16
export const FormProps = {
14
17
layout : PropTypes . oneOf ( [ 'horizontal' , 'inline' , 'vertical' ] ) ,
@@ -66,6 +69,7 @@ const Form = {
66
69
created ( ) {
67
70
this . fields = [ ] ;
68
71
this . form = undefined ;
72
+ this . lastValidatePromise = null ;
69
73
provide ( 'FormContext' , this ) ;
70
74
} ,
71
75
setup ( ) {
@@ -100,12 +104,16 @@ const Form = {
100
104
e . preventDefault ( ) ;
101
105
e . stopPropagation ( ) ;
102
106
this . $emit ( 'submit' , e ) ;
103
- const res = this . validate ( ) ;
107
+ const res = this . validateFields ( ) ;
104
108
res
105
109
. then ( values => {
110
+ // eslint-disable-next-line no-console
111
+ console . log ( 'values' , values ) ;
106
112
this . $emit ( 'finish' , values ) ;
107
113
} )
108
114
. catch ( errors => {
115
+ // eslint-disable-next-line no-console
116
+ console . log ( 'errors' , errors ) ;
109
117
this . handleFinishFailed ( errors ) ;
110
118
} ) ;
111
119
} ,
@@ -179,74 +187,98 @@ const Form = {
179
187
// }
180
188
} ,
181
189
scrollToField ( ) { } ,
182
- getFieldsValue ( allFields ) {
190
+ // TODO
191
+ // eslint-disable-next-line no-unused-vars
192
+ getFieldsValue ( nameList ) {
183
193
const values = { } ;
184
- allFields . forEach ( ( { prop, fieldValue } ) => {
194
+ this . fields . forEach ( ( { prop, fieldValue } ) => {
185
195
values [ prop ] = fieldValue ;
186
196
} ) ;
187
197
return values ;
188
198
} ,
189
- validateFields ( ) {
190
- return this . validateField ( ...arguments ) ;
191
- } ,
192
- validateField ( ns , opt , cb ) {
193
- const pending = new Promise ( ( resolve , reject ) => {
194
- const params = getParams ( ns , opt , cb ) ;
195
- const { names, options } = params ;
196
- let { callback } = params ;
197
- if ( ! callback || typeof callback === 'function' ) {
198
- const oldCb = callback ;
199
- callback = ( errorFields , values ) => {
200
- if ( oldCb ) {
201
- oldCb ( errorFields , values ) ;
202
- } else if ( errorFields ) {
203
- reject ( { errorFields, values } ) ;
204
- } else {
205
- resolve ( values ) ;
206
- }
207
- } ;
199
+ validateFields ( nameList , options ) {
200
+ if ( ! this . model ) {
201
+ warning ( false , 'Form' , 'model is required for validateFields to work.' ) ;
202
+ return ;
203
+ }
204
+ const provideNameList = ! ! nameList ;
205
+ const namePathList = provideNameList ? toArray ( nameList ) . map ( getNamePath ) : [ ] ;
206
+
207
+ // Collect result in promise list
208
+ const promiseList = [ ] ;
209
+
210
+ this . fields . forEach ( field => {
211
+ // Add field if not provide `nameList`
212
+ if ( ! provideNameList ) {
213
+ namePathList . push ( field . getNamePath ( ) ) ;
208
214
}
209
- const allFields = names
210
- ? this . fields . filter ( field => names . indexOf ( field . prop ) !== - 1 )
211
- : this . fields ;
212
- const fields = allFields . filter ( field => {
213
- const rules = field . getFilteredRule ( '' ) ;
214
- return rules && rules . length ;
215
- } ) ;
216
- if ( ! fields . length ) {
217
- callback ( null , this . getFieldsValue ( allFields ) ) ;
215
+
216
+ // Skip if without rule
217
+ if ( ! field . getRules ( ) . length ) {
218
218
return ;
219
219
}
220
- if ( ! ( 'firstFields' in options ) ) {
221
- options . firstFields = allFields . filter ( field => {
222
- return ! ! field . validateFirst ;
220
+
221
+ const fieldNamePath = field . getNamePath ( ) ;
222
+
223
+ // Add field validate rule in to promise list
224
+ if ( ! provideNameList || containsNamePath ( namePathList , fieldNamePath ) ) {
225
+ const promise = field . validateRules ( {
226
+ validateMessages : {
227
+ ...defaultValidateMessages ,
228
+ ...this . validateMessages ,
229
+ } ,
230
+ ...options ,
223
231
} ) ;
232
+
233
+ // Wrap promise with field
234
+ promiseList . push (
235
+ promise
236
+ . then ( ( ) => ( { name : fieldNamePath , errors : [ ] } ) )
237
+ . catch ( errors =>
238
+ Promise . reject ( {
239
+ name : fieldNamePath ,
240
+ errors,
241
+ } ) ,
242
+ ) ,
243
+ ) ;
224
244
}
225
- let fieldsErrors = { } ;
226
- let valid = true ;
227
- let count = 0 ;
228
- const promiseList = [ ] ;
229
- fields . forEach ( field => {
230
- const promise = field . validate ( '' , errors => {
231
- if ( errors ) {
232
- valid = false ;
233
- fieldsErrors [ field . prop ] = errors ;
234
- }
245
+ } ) ;
246
+
247
+ const summaryPromise = allPromiseFinish ( promiseList ) ;
248
+ this . lastValidatePromise = summaryPromise ;
249
+
250
+ // // Notify fields with rule that validate has finished and need update
251
+ // summaryPromise
252
+ // .catch(results => results)
253
+ // .then(results => {
254
+ // const resultNamePathList = results.map(({ name }) => name);
255
+ // // eslint-disable-next-line no-console
256
+ // console.log(resultNamePathList);
257
+ // });
235
258
236
- if ( ++ count === fields . length ) {
237
- callback ( valid ? null : fieldsErrors , this . getFieldsValue ( fields ) ) ;
238
- }
259
+ const returnPromise = summaryPromise
260
+ . then ( ( ) => {
261
+ if ( this . lastValidatePromise === summaryPromise ) {
262
+ return Promise . resolve ( this . getFieldsValue ( namePathList ) ) ;
263
+ }
264
+ return Promise . reject ( [ ] ) ;
265
+ } )
266
+ . catch ( results => {
267
+ const errorList = results . filter ( result => result && result . errors . length ) ;
268
+ return Promise . reject ( {
269
+ values : this . getFieldsValue ( namePathList ) ,
270
+ errorFields : errorList ,
271
+ outOfDate : this . lastValidatePromise !== summaryPromise ,
239
272
} ) ;
240
- promiseList . push ( promise . then ( ( ) => { } ) ) ;
241
273
} ) ;
242
- } ) ;
243
- pending . catch ( e => {
244
- if ( console . error && process . env . NODE_ENV !== 'production' ) {
245
- console . error ( e ) ;
246
- }
247
- return e ;
248
- } ) ;
249
- return pending ;
274
+
275
+ // Do not throw in console
276
+ returnPromise . catch ( e => e ) ;
277
+
278
+ return returnPromise ;
279
+ } ,
280
+ validateField ( ) {
281
+ return this . validateFields ( ... arguments ) ;
250
282
} ,
251
283
} ,
252
284
0 commit comments