Skip to content

Commit 6f401e5

Browse files
committed
fix: summary validate logic
1 parent efa74e9 commit 6f401e5

File tree

8 files changed

+54
-21
lines changed

8 files changed

+54
-21
lines changed

src/Field.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
346346
}
347347
};
348348

349-
public validateRules = (options?: ValidateOptions): Promise<string[]> => {
349+
public validateRules = (options?: ValidateOptions): Promise<RuleError[]> => {
350350
const prevErrors = this.errors;
351351
const prevWarnings = this.warnings;
352352

src/FieldContext.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import warning from 'rc-util/lib/warning';
3-
import { InternalFormInstance } from './interface';
3+
import type { InternalFormInstance } from './interface';
44

55
export const HOOK_MARK = 'RC_FORM_INTERNAL_HOOKS';
66

@@ -13,6 +13,7 @@ const Context = React.createContext<InternalFormInstance>({
1313
getFieldValue: warningFunc,
1414
getFieldsValue: warningFunc,
1515
getFieldError: warningFunc,
16+
getFieldWarning: warningFunc,
1617
getFieldsError: warningFunc,
1718
isFieldsTouched: warningFunc,
1819
isFieldTouched: warningFunc,

src/interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export interface FieldEntity {
101101
isListField: () => boolean;
102102
isList: () => boolean;
103103
isPreserve: () => boolean;
104-
validateRules: (options?: ValidateOptions) => Promise<string[]>;
104+
validateRules: (options?: ValidateOptions) => Promise<RuleError[]>;
105105
getMeta: () => Meta;
106106
getNamePath: () => InternalNamePath;
107107
getErrors: () => string[];

src/useForm.ts

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import type {
2020
Meta,
2121
InternalFieldData,
2222
ValuedNotifyInfo,
23+
RuleError,
2324
} from './interface';
2425
import { HOOK_MARK } from './FieldContext';
2526
import { allPromiseFinish } from './utils/asyncUtil';
@@ -740,10 +741,7 @@ export class FormStore {
740741
: [];
741742

742743
// Collect result in promise list
743-
const promiseList: Promise<{
744-
name: InternalNamePath;
745-
errors: string[];
746-
}>[] = [];
744+
const promiseList: Promise<FieldError>[] = [];
747745

748746
this.getFieldEntities(true).forEach((field: FieldEntity) => {
749747
// Add field if not provide `nameList`
@@ -785,13 +783,33 @@ export class FormStore {
785783
// Wrap promise with field
786784
promiseList.push(
787785
promise
788-
.then(() => ({ name: fieldNamePath, errors: [] }))
789-
.catch(errors =>
790-
Promise.reject({
786+
.then<any, RuleError>(() => ({ name: fieldNamePath, errors: [], warnings: [] }))
787+
.catch((ruleErrors: RuleError[]) => {
788+
const mergedErrors: string[] = [];
789+
const mergedWarnings: string[] = [];
790+
791+
ruleErrors.forEach(({ rule: { warningOnly }, errors }) => {
792+
if (warningOnly) {
793+
mergedWarnings.push(...errors);
794+
} else {
795+
mergedErrors.push(...errors);
796+
}
797+
});
798+
799+
if (mergedErrors.length) {
800+
return Promise.reject({
801+
name: fieldNamePath,
802+
errors: mergedErrors,
803+
warnings: mergedWarnings,
804+
});
805+
}
806+
807+
return {
791808
name: fieldNamePath,
792-
errors,
793-
}),
794-
),
809+
errors: mergedErrors,
810+
warnings: mergedWarnings,
811+
};
812+
}),
795813
);
796814
}
797815
});

src/utils/asyncUtil.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FieldError } from '../interface';
1+
import type { FieldError } from '../interface';
22

33
export function allPromiseFinish(promiseList: Promise<FieldError>[]): Promise<FieldError[]> {
44
let hasError = false;

tests/context.test.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,14 @@ describe('Form.Context', () => {
3535
'form1',
3636
expect.objectContaining({
3737
changedFields: [
38-
{ errors: [], name: ['username'], touched: true, validating: false, value: 'Light' },
38+
{
39+
errors: [],
40+
warnings: [],
41+
name: ['username'],
42+
touched: true,
43+
validating: false,
44+
value: 'Light',
45+
},
3946
],
4047
forms: {
4148
form1: expect.objectContaining({}),

tests/index.test.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,20 +135,23 @@ describe('Form.Basic', () => {
135135
expect(form.isFieldTouched('username')).toBeFalsy();
136136
expect(onError).not.toHaveBeenCalled();
137137
expect(onReset).toHaveBeenCalled();
138+
onError.mockRestore();
138139
onReset.mockRestore();
139140

140141
await changeValue(getField(wrapper, 'username'), '');
141142
expect(form.getFieldValue('username')).toEqual('');
142143
expect(form.getFieldError('username')).toEqual(["'username' is required"]);
143144
expect(form.isFieldTouched('username')).toBeTruthy();
144-
expect(onError).toHaveBeenCalledWith(["'username' is required"]);
145+
expect(onError).toHaveBeenCalledWith(["'username' is required"], []);
145146
expect(onReset).not.toHaveBeenCalled();
147+
onError.mockRestore();
148+
onReset.mockRestore();
146149

147150
form.resetFields(...args);
148151
expect(form.getFieldValue('username')).toEqual(undefined);
149152
expect(form.getFieldError('username')).toEqual([]);
150153
expect(form.isFieldTouched('username')).toBeFalsy();
151-
expect(onError).toHaveBeenCalledWith([]);
154+
expect(onError).toHaveBeenCalledWith([], []);
152155
expect(onReset).toHaveBeenCalled();
153156
});
154157
}
@@ -287,7 +290,7 @@ describe('Form.Basic', () => {
287290
matchError(wrapper, "'user' is required");
288291
expect(onFinish).not.toHaveBeenCalled();
289292
expect(onFinishFailed).toHaveBeenCalledWith({
290-
errorFields: [{ name: ['user'], errors: ["'user' is required"] }],
293+
errorFields: [{ name: ['user'], errors: ["'user' is required"], warnings: [] }],
291294
outOfDate: false,
292295
values: {},
293296
});
@@ -643,7 +646,7 @@ describe('Form.Basic', () => {
643646

644647
expect(
645648
form.getFieldsValue(null, meta => {
646-
expect(Object.keys(meta)).toEqual(['touched', 'validating', 'errors', 'name']);
649+
expect(Object.keys(meta)).toEqual(['touched', 'validating', 'errors', 'warnings', 'name']);
647650
return false;
648651
}),
649652
).toEqual({});

tests/validate.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe('Form.Validate', () => {
2929
{
3030
name: ['username'],
3131
errors: ["'username' is required"],
32+
warnings: [],
3233
},
3334
]);
3435

@@ -37,10 +38,12 @@ describe('Form.Validate', () => {
3738
{
3839
name: ['username'],
3940
errors: ["'username' is required"],
41+
warnings: [],
4042
},
4143
{
4244
name: ['not-exist'],
4345
errors: [],
46+
warnings: [],
4447
},
4548
]);
4649
});
@@ -412,7 +415,7 @@ describe('Form.Validate', () => {
412415
})
413416
.then(() => {
414417
expect(failed).toBeTruthy();
415-
resolve();
418+
resolve('');
416419
});
417420
});
418421
});
@@ -465,7 +468,7 @@ describe('Form.Validate', () => {
465468
validator: () =>
466469
new Promise(resolve => {
467470
if (canEnd) {
468-
resolve();
471+
resolve('');
469472
}
470473
}),
471474
},
@@ -483,6 +486,7 @@ describe('Form.Validate', () => {
483486
{
484487
name: ['username'],
485488
errors: ["'username' is required"],
489+
warnings: [],
486490
},
487491
]);
488492
expect(onFinish).not.toHaveBeenCalled();

0 commit comments

Comments
 (0)