Skip to content

Commit 523824a

Browse files
committed
feat: validation schema support
1 parent 3c74681 commit 523824a

5 files changed

Lines changed: 30 additions & 7 deletions

File tree

packages/core/src/Observer.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,16 @@ export const ValidationObserver = defineComponent({
1111
type: String,
1212
default: undefined,
1313
},
14+
validationSchema: {
15+
type: Object,
16+
default: undefined,
17+
},
1418
},
1519
setup(props, ctx) {
16-
const { form, errors, validate, handleSubmit, handleReset, values, ...flags } = useForm();
20+
const { form, errors, validate, handleSubmit, handleReset, values, ...flags } = useForm({
21+
validationSchema: props.validationSchema,
22+
});
23+
1724
provide('$_veeObserver', form);
1825

1926
const slotProps = computed(() => {

packages/core/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export interface FieldComposite extends Record<Flag, Ref<boolean>> {
8686
failedRules: Ref<Record<string, string>>;
8787
errors: Ref<string[]>;
8888
errorMessage: Ref<string | undefined>;
89+
__setRules(fn: GenericValidateFunction): void;
8990
}
9091

9192
export interface FormController {

packages/core/src/useField.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ type RuleExpression = MaybeReactive<string | Record<string, any> | GenericValida
2222
export function useField(fieldName: MaybeReactive<string>, rules: RuleExpression, opts?: FieldOptions): FieldComposite {
2323
const { value, form, immediate } = useFieldOptions(opts);
2424
const { flags, errors, failedRules, onBlur, handleChange, reset, patch } = useValidationState(value);
25+
let schemaValidation: GenericValidateFunction;
2526
const normalizedRules = computed(() => {
26-
return normalizeRules(unwrap(rules));
27+
return schemaValidation || normalizeRules(unwrap(rules));
2728
});
2829

2930
const validateField = async (): Promise<ValidationResult> => {
@@ -78,6 +79,9 @@ export function useField(fieldName: MaybeReactive<string>, rules: RuleExpression
7879
validate: validateField,
7980
handleChange,
8081
onBlur,
82+
__setRules(fn: GenericValidateFunction) {
83+
schemaValidation = fn;
84+
},
8185
};
8286

8387
useFormController(field, normalizedRules, form);

packages/core/src/useForm.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { computed, ref, Ref } from 'vue';
2-
import { Flag, FormController, SubmissionHandler } from './types';
2+
import { Flag, FormController, SubmissionHandler, GenericValidateFunction } from './types';
33
import { unwrap } from './utils/refs';
44

55
const mergeStrategies: Record<Flag, 'every' | 'some'> = {
@@ -29,7 +29,11 @@ function computeFlags(fields: Ref<any[]>) {
2929
}, {} as Record<Flag, Ref<boolean>>);
3030
}
3131

32-
export function useForm() {
32+
interface FormOptions {
33+
validationSchema: Record<string, GenericValidateFunction>;
34+
}
35+
36+
export function useForm(opts?: FormOptions) {
3337
const fields: Ref<any[]> = ref([]);
3438
const fieldsById: Record<string, any> = {};
3539
const values = computed(() => {
@@ -50,8 +54,14 @@ export function useForm() {
5054

5155
const controller: FormController = {
5256
register(field) {
57+
const vid = unwrap(field.vid);
58+
// Set the rules for that field from the schema.
59+
if (opts?.validationSchema[vid]) {
60+
field.__setRules(opts?.validationSchema[vid]);
61+
}
62+
5363
fields.value.push(field);
54-
fieldsById[unwrap(field.vid)] = field;
64+
fieldsById[vid] = field;
5565
},
5666
fields: fieldsById,
5767
values,

packages/core/src/validate.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ async function _validate(field: FieldContext, value: any) {
7474
// if a generic function, use it as the pipeline.
7575
if (isCallable(field.rules)) {
7676
const result = await field.rules(value);
77+
const isValid = typeof result !== 'string' && result;
7778

7879
return {
79-
valid: typeof result === 'string' || !result,
80-
errors: typeof result === 'string' ? [{ msg: result, rule: '' }] : [],
80+
valid: isValid,
81+
errors: !isValid ? [{ msg: result, rule: '' }] : [],
8182
};
8283
}
8384

0 commit comments

Comments
 (0)