Skip to content

Commit d68d455

Browse files
committed
feat(useForm): Set errors only for touched fields on 'blur' validation mode
1 parent 1df8a83 commit d68d455

File tree

1 file changed

+37
-3
lines changed

1 file changed

+37
-3
lines changed

packages/core/src/composables/useForm.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ interface FieldArrayRegistry {
4949
};
5050
}
5151

52+
interface ValidateHandlerOptions {
53+
onlyBlurred?: boolean;
54+
}
55+
5256
export interface FormSubmitHelper<Values extends FormValues> {
5357
setSubmitting: (isSubmitting: boolean) => void;
5458
readonly initialValues: Values;
@@ -262,7 +266,7 @@ export function useForm<
262266
});
263267

264268
return validateTiming.value === 'blur'
265-
? runAllValidateHandler(state.values)
269+
? runAllValidateHandler(state.values, { onlyBlurred: true })
266270
: Promise.resolve();
267271
};
268272

@@ -503,20 +507,50 @@ export function useForm<
503507
});
504508
};
505509

506-
const runAllValidateHandler = (values: Values = state.values) => {
510+
/**
511+
* Creates a new object of errors, but only with the errors of touched fields.
512+
*
513+
* @param errors The union of field and form errors
514+
* @returns The field errors that have been touched
515+
*/
516+
const getTouchedErrors = (errors: FormErrors<Values>) => {
517+
const touchedFieldsKeys: any = [];
518+
519+
Object.entries(state.touched.value).forEach(([key, isTouched]) => {
520+
if (isTouched) {
521+
touchedFieldsKeys.push(key);
522+
}
523+
});
524+
525+
const touchedErrorsEntries: Array<[keyof FormErrors<Values>, string]> =
526+
Object.entries(errors).filter(([key]) => {
527+
return touchedFieldsKeys.includes(key);
528+
});
529+
530+
return Object.fromEntries(touchedErrorsEntries) as FormErrors<Values>;
531+
};
532+
533+
const runAllValidateHandler = (
534+
values: Values = state.values,
535+
validateOptions?: ValidateHandlerOptions,
536+
) => {
507537
dispatch({ type: ACTION_TYPE.SET_ISVALIDATING, payload: true });
508538
return Promise.all([
509539
runFieldValidateHandler(values),
510540
options.validate ? runValidateHandler(values) : {},
511541
])
512542
.then(([fieldErrors, validateErrors]) => {
513-
const errors = deepmerge.all<FormErrors<Values>>(
543+
const baseErrors = deepmerge.all<FormErrors<Values>>(
514544
[fieldErrors, validateErrors],
515545
{
516546
arrayMerge,
517547
},
518548
);
519549

550+
const errors = validateOptions?.onlyBlurred
551+
? getTouchedErrors(baseErrors)
552+
: baseErrors;
553+
520554
setErrors(errors);
521555

522556
return errors;

0 commit comments

Comments
 (0)