From 707760a8d093d1db2db18ac442b2926a40f0c847 Mon Sep 17 00:00:00 2001 From: YuanHeDx <96035115+YuanHeDx@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:34:56 +0800 Subject: [PATCH] fix: fix FormModel.validateIn only match one pattern (#124) --- .../form/__tests__/field-model.test.ts | 24 +++++++++++++++++ .../node-engine/form/src/core/field-model.ts | 26 ++++++++++--------- .../node-engine/form/src/core/form-model.ts | 10 ++++--- 3 files changed, 44 insertions(+), 16 deletions(-) diff --git a/packages/node-engine/form/__tests__/field-model.test.ts b/packages/node-engine/form/__tests__/field-model.test.ts index 52cf6e91..66a6d2de 100644 --- a/packages/node-engine/form/__tests__/field-model.test.ts +++ b/packages/node-engine/form/__tests__/field-model.test.ts @@ -195,6 +195,30 @@ describe('FieldModel', () => { 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 的能力,所以注释这个单测 // it('can trigger validate from parent', async () => { // formModel.init({ diff --git a/packages/node-engine/form/src/core/field-model.ts b/packages/node-engine/form/src/core/field-model.ts index a1ceb95c..3be8b089 100644 --- a/packages/node-engine/form/src/core/field-model.ts +++ b/packages/node-engine/form/src/core/field-model.ts @@ -7,9 +7,9 @@ import { toFeedback } from '../utils/validate'; import { FieldModelState, FieldName, FieldValue, Ref } from '../types/field'; import { Errors, + FeedbackLevel, FieldError, FieldWarning, - isFieldWarning, Validate, ValidateTrigger, Warnings, @@ -343,24 +343,26 @@ export class FieldModel implements Dispo errors?: FieldError[]; warnings?: FieldWarning[]; }> { - const errors: FieldError[] = []; - const warnings: FieldWarning[] = []; + let errors: FieldError[] = []; + let warnings: FieldWarning[] = []; - const result = await this.form.validateIn(this.name); - if (!result) { + const results = await this.form.validateIn(this.name); + if (!results?.length) { return {}; } 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 {}; } - if (isFieldWarning(feedback)) { - warnings.push(feedback); - } else { - errors.push(feedback); - } + const groupedFeedbacks = groupBy(feedbacks, 'level'); + + warnings = warnings.concat(groupedFeedbacks[FeedbackLevel.Warning] as FieldWarning[]); + errors = errors.concat(groupedFeedbacks[FeedbackLevel.Error] as FieldError[]); } return { errors, warnings }; diff --git a/packages/node-engine/form/src/core/form-model.ts b/packages/node-engine/form/src/core/form-model.ts index 988ef845..66f70885 100644 --- a/packages/node-engine/form/src/core/form-model.ts +++ b/packages/node-engine/form/src/core/form-model.ts @@ -239,12 +239,12 @@ export class FormModel implements Disposable { return; } - const validateKey = Object.keys(this._options.validate).find((pattern) => + const validateKeys = Object.keys(this._options.validate).filter((pattern) => Glob.isMatch(pattern, name) ); - if (validateKey) { - const validate = this._options.validate[validateKey]; + const validatePromises = validateKeys.map(async (validateKey) => { + const validate = this._options.validate![validateKey]; return validate({ value: this.getValueIn(name), @@ -252,7 +252,9 @@ export class FormModel implements Disposable { context: this.context, name, }); - } + }); + + return Promise.all(validatePromises); } async validate(): Promise {