Skip to content

Commit

Permalink
feat: allow multiple messages in a validator fn closes #4322 #4318
Browse files Browse the repository at this point in the history
  • Loading branch information
logaretm committed Jun 20, 2023
1 parent 1c3ed01 commit 2cf0eec
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-laws-drive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vee-validate': patch
---

feat: allow multiple messages in a validator fn closes #4322 #4318
2 changes: 2 additions & 0 deletions packages/vee-validate/src/types/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export type GenericObject = Record<string, any>;

export type MaybeArray<T> = T | T[];

export type MaybePromise<T> = T | Promise<T>;

export type MapValuesPathsToRefs<
TValues extends GenericObject,
TPaths extends readonly [...MaybeRef<Path<TValues>>[]]
Expand Down
4 changes: 2 additions & 2 deletions packages/vee-validate/src/types/forms.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ComputedRef, DeepReadonly, Ref, MaybeRef, MaybeRefOrGetter } from 'vue';
import { MapValuesPathsToRefs, GenericObject } from './common';
import { MapValuesPathsToRefs, GenericObject, MaybeArray, MaybePromise } from './common';
import { FieldValidationMetaInfo } from '../../../shared';
import { Path, PathValue } from './paths';
import { PartialDeep } from 'type-fest';
Expand Down Expand Up @@ -149,7 +149,7 @@ export type FieldContext<TValue = unknown> = Omit<PrivateFieldContext<TValue>, '
export type GenericValidateFunction<TValue = unknown> = (
value: TValue,
ctx: FieldValidationMetaInfo
) => boolean | string | Promise<boolean | string>;
) => MaybePromise<boolean | MaybeArray<string>>;

export interface FormState<TValues> {
values: PartialDeep<TValues>;
Expand Down
10 changes: 7 additions & 3 deletions packages/vee-validate/src/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,17 @@ async function _validate<TValue = unknown>(field: FieldValidationContext<TValue>
for (let i = 0; i < length; i++) {
const rule = pipeline[i];
const result = await rule(value, ctx);
const isValid = typeof result !== 'string' && result;
const isValid = typeof result !== 'string' && !Array.isArray(result) && result;
if (isValid) {
continue;
}

const message = typeof result === 'string' ? result : _generateFieldError(ctx);
errors.push(message);
if (Array.isArray(result)) {
errors.push(...result);
} else {
const message = typeof result === 'string' ? result : _generateFieldError(ctx);
errors.push(message);
}

if (field.bails) {
return {
Expand Down
20 changes: 20 additions & 0 deletions packages/vee-validate/tests/useField.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -893,4 +893,24 @@ describe('useField()', () => {
await flushPromises();
expect(field.value.value).toBe(123);
});

test('a validator can return multiple messages', async () => {
let field!: FieldContext;
const validator = vi.fn(val => (val ? true : [REQUIRED_MESSAGE, 'second']));

mountWithHoc({
setup() {
field = useField('field', validator);

return {};
},
});

await flushPromises();
expect(field.errors.value).toHaveLength(0);
await field.validate();
await flushPromises();
expect(field.errors.value).toHaveLength(2);
expect(field.errors.value).toEqual([REQUIRED_MESSAGE, 'second']);
});
});

0 comments on commit 2cf0eec

Please sign in to comment.