fix: fix FormModel.validateIn only match one pattern (#124)

This commit is contained in:
YuanHeDx 2025-04-03 11:34:56 +08:00 committed by GitHub
parent 03dab3a764
commit 707760a8d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 16 deletions

View File

@ -195,6 +195,30 @@ describe('FieldModel', () => {
expect(other.validate).toHaveBeenCalledTimes(0); expect(other.validate).toHaveBeenCalledTimes(0);
}); });
it('should validate when multiple pattern match ', async () => {
const validate1 = vi.fn();
const validate2 = vi.fn();
formModel.init({
validateTrigger: ValidateTrigger.onChange,
validate: {
'a.*.input': validate1,
'a.1.input': validate2,
},
initialValues: {
a: [{ input: '0' }, { input: '1' }],
},
});
const root = formModel.createField('a');
const i0 = formModel.createField('a.0.input');
const i1 = formModel.createField('a.1.input');
formModel.setValueIn('a.1.input', 'xxx');
expect(validate1).toHaveBeenCalledTimes(1);
expect(validate2).toHaveBeenCalledTimes(1);
});
// 暂时注释了从 parent 触发validate 的能力,所以注释这个单测 // 暂时注释了从 parent 触发validate 的能力,所以注释这个单测
// it('can trigger validate from parent', async () => { // it('can trigger validate from parent', async () => {
// formModel.init({ // formModel.init({

View File

@ -7,9 +7,9 @@ import { toFeedback } from '../utils/validate';
import { FieldModelState, FieldName, FieldValue, Ref } from '../types/field'; import { FieldModelState, FieldName, FieldValue, Ref } from '../types/field';
import { import {
Errors, Errors,
FeedbackLevel,
FieldError, FieldError,
FieldWarning, FieldWarning,
isFieldWarning,
Validate, Validate,
ValidateTrigger, ValidateTrigger,
Warnings, Warnings,
@ -343,24 +343,26 @@ export class FieldModel<TValue extends FieldValue = FieldValue> implements Dispo
errors?: FieldError[]; errors?: FieldError[];
warnings?: FieldWarning[]; warnings?: FieldWarning[];
}> { }> {
const errors: FieldError[] = []; let errors: FieldError[] = [];
const warnings: FieldWarning[] = []; let warnings: FieldWarning[] = [];
const result = await this.form.validateIn(this.name); const results = await this.form.validateIn(this.name);
if (!result) { if (!results?.length) {
return {}; return {};
} else { } else {
const feedback = toFeedback(result, this.name); const feedbacks = results.map((result) => toFeedback(result, this.name)).filter(Boolean) as (
| FieldError
| FieldWarning
)[];
if (!feedback) { if (!feedbacks?.length) {
return {}; return {};
} }
if (isFieldWarning(feedback)) { const groupedFeedbacks = groupBy(feedbacks, 'level');
warnings.push(feedback);
} else { warnings = warnings.concat(groupedFeedbacks[FeedbackLevel.Warning] as FieldWarning[]);
errors.push(feedback); errors = errors.concat(groupedFeedbacks[FeedbackLevel.Error] as FieldError[]);
}
} }
return { errors, warnings }; return { errors, warnings };

View File

@ -239,12 +239,12 @@ export class FormModel<TValues = any> implements Disposable {
return; return;
} }
const validateKey = Object.keys(this._options.validate).find((pattern) => const validateKeys = Object.keys(this._options.validate).filter((pattern) =>
Glob.isMatch(pattern, name) Glob.isMatch(pattern, name)
); );
if (validateKey) { const validatePromises = validateKeys.map(async (validateKey) => {
const validate = this._options.validate[validateKey]; const validate = this._options.validate![validateKey];
return validate({ return validate({
value: this.getValueIn(name), value: this.getValueIn(name),
@ -252,7 +252,9 @@ export class FormModel<TValues = any> implements Disposable {
context: this.context, context: this.context,
name, name,
}); });
} });
return Promise.all(validatePromises);
} }
async validate(): Promise<FormValidateReturn> { async validate(): Promise<FormValidateReturn> {