Skip to content

Commit

Permalink
feat(useForm): Set errors only for touched fields on 'blur' validatio…
Browse files Browse the repository at this point in the history
…n mode
  • Loading branch information
christianlmc committed Aug 7, 2023
1 parent 1df8a83 commit d68d455
Showing 1 changed file with 37 additions and 3 deletions.
40 changes: 37 additions & 3 deletions packages/core/src/composables/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ interface FieldArrayRegistry {
};
}

interface ValidateHandlerOptions {
onlyBlurred?: boolean;
}

export interface FormSubmitHelper<Values extends FormValues> {
setSubmitting: (isSubmitting: boolean) => void;
readonly initialValues: Values;
Expand Down Expand Up @@ -262,7 +266,7 @@ export function useForm<
});

return validateTiming.value === 'blur'
? runAllValidateHandler(state.values)
? runAllValidateHandler(state.values, { onlyBlurred: true })
: Promise.resolve();
};

Expand Down Expand Up @@ -503,20 +507,50 @@ export function useForm<
});
};

const runAllValidateHandler = (values: Values = state.values) => {
/**
* Creates a new object of errors, but only with the errors of touched fields.
*
* @param errors The union of field and form errors
* @returns The field errors that have been touched
*/
const getTouchedErrors = (errors: FormErrors<Values>) => {
const touchedFieldsKeys: any = [];

Object.entries(state.touched.value).forEach(([key, isTouched]) => {
if (isTouched) {
touchedFieldsKeys.push(key);
}
});

const touchedErrorsEntries: Array<[keyof FormErrors<Values>, string]> =
Object.entries(errors).filter(([key]) => {
return touchedFieldsKeys.includes(key);
});

return Object.fromEntries(touchedErrorsEntries) as FormErrors<Values>;
};

const runAllValidateHandler = (
values: Values = state.values,
validateOptions?: ValidateHandlerOptions,
) => {
dispatch({ type: ACTION_TYPE.SET_ISVALIDATING, payload: true });
return Promise.all([
runFieldValidateHandler(values),
options.validate ? runValidateHandler(values) : {},
])
.then(([fieldErrors, validateErrors]) => {
const errors = deepmerge.all<FormErrors<Values>>(
const baseErrors = deepmerge.all<FormErrors<Values>>(
[fieldErrors, validateErrors],
{
arrayMerge,
},
);

const errors = validateOptions?.onlyBlurred
? getTouchedErrors(baseErrors)
: baseErrors;

setErrors(errors);

return errors;
Expand Down

0 comments on commit d68d455

Please sign in to comment.