Skip to content

Commit 5f8d8a5

Browse files
committed
fix: form validateFirst not reject #4273
1 parent 4a0fce5 commit 5f8d8a5

File tree

5 files changed

+157
-136
lines changed

5 files changed

+157
-136
lines changed

components/form/Form.tsx

+33-7
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ import initDefaultProps from '../_util/props-util/initDefaultProps';
1616
import type { VueNode } from '../_util/type';
1717
import { tuple } from '../_util/type';
1818
import type { ColProps } from '../grid/Col';
19-
import type { InternalNamePath, NamePath, ValidateErrorEntity, ValidateOptions } from './interface';
19+
import type {
20+
InternalNamePath,
21+
NamePath,
22+
RuleError,
23+
ValidateErrorEntity,
24+
ValidateOptions,
25+
} from './interface';
2026
import { useInjectSize } from '../_util/hooks/useSize';
2127
import useConfigInject from '../_util/hooks/useConfigInject';
2228
import { useProvideForm } from './context';
@@ -247,13 +253,33 @@ const Form = defineComponent({
247253
// Wrap promise with field
248254
promiseList.push(
249255
promise
250-
.then(() => ({ name: fieldNamePath, errors: [] }))
251-
.catch((errors: any) =>
252-
Promise.reject({
256+
.then<any, RuleError>(() => ({ name: fieldNamePath, errors: [], warnings: [] }))
257+
.catch((ruleErrors: RuleError[]) => {
258+
const mergedErrors: string[] = [];
259+
const mergedWarnings: string[] = [];
260+
261+
ruleErrors.forEach(({ rule: { warningOnly }, errors }) => {
262+
if (warningOnly) {
263+
mergedWarnings.push(...errors);
264+
} else {
265+
mergedErrors.push(...errors);
266+
}
267+
});
268+
269+
if (mergedErrors.length) {
270+
return Promise.reject({
271+
name: fieldNamePath,
272+
errors: mergedErrors,
273+
warnings: mergedWarnings,
274+
});
275+
}
276+
277+
return {
253278
name: fieldNamePath,
254-
errors,
255-
}),
256-
),
279+
errors: mergedErrors,
280+
warnings: mergedWarnings,
281+
};
282+
}),
257283
);
258284
}
259285
});

components/form/FormItem.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { toArray } from './utils/typeUtil';
1313
import { warning } from '../vc-util/warning';
1414
import find from 'lodash-es/find';
1515
import { tuple } from '../_util/type';
16-
import type { InternalNamePath, RuleObject, ValidateOptions } from './interface';
16+
import type { InternalNamePath, RuleError, RuleObject, ValidateOptions } from './interface';
1717
import useConfigInject from '../_util/hooks/useConfigInject';
1818
import { useInjectForm } from './context';
1919
import FormItemLabel from './FormItemLabel';
@@ -31,7 +31,7 @@ export interface FieldExpose {
3131
clearValidate: () => void;
3232
namePath: ComputedRef<InternalNamePath>;
3333
rules?: ComputedRef<ValidationRule[]>;
34-
validateRules: (options: ValidateOptions) => Promise<void> | Promise<string[]>;
34+
validateRules: (options: ValidateOptions) => Promise<void> | Promise<RuleError[]>;
3535
}
3636

3737
function getPropByPath(obj: any, namePathList: any, strict?: boolean) {
@@ -209,10 +209,12 @@ export default defineComponent({
209209

210210
promise
211211
.catch(e => e)
212-
.then((ers = []) => {
212+
.then((results: RuleError[] = []) => {
213213
if (validateState.value === 'validating') {
214-
validateState.value = ers.length ? 'error' : 'success';
215-
errors.value = ers;
214+
const res = results.filter(result => result && result.errors.length);
215+
validateState.value = res.length ? 'error' : 'success';
216+
217+
errors.value = res.map(r => r.errors);
216218
}
217219
});
218220

components/form/interface.ts

+7
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ type Validator = (
5050
) => Promise<void> | void;
5151

5252
export interface ValidatorRule {
53+
warningOnly?: boolean;
5354
message?: string | VueNode;
5455
validator: Validator;
5556
}
5657

5758
interface BaseRule {
59+
warningOnly?: boolean;
5860
enum?: StoreValue[];
5961
len?: number;
6062
max?: number;
@@ -92,6 +94,11 @@ export interface FieldError {
9294
errors: string[];
9395
}
9496

97+
export interface RuleError {
98+
errors: string[];
99+
rule: RuleObject;
100+
}
101+
95102
export interface ValidateOptions {
96103
triggerName?: string;
97104
validateMessages?: ValidateMessages;

components/form/utils/asyncUtil.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { FieldError } from '../interface';
2+
23
export function allPromiseFinish(promiseList: Promise<FieldError>[]): Promise<FieldError[]> {
34
let hasError = false;
45
let count = promiseList.length;
5-
const results = [];
6+
const results: FieldError[] = [];
67

78
if (!promiseList.length) {
89
return Promise.resolve([]);

0 commit comments

Comments
 (0)