I have 2 controlled inputs on a form, and I only need to validate that 1 of them is filled in. I'm having trouble with the validation logic.
function atLeastOneChecked(inputs: string) {
return inputs.length > 0;
}
<Controller
control={control}
{...register("phoneNumber", {
validate: atLeastOneChecked,
})}
render={({ field, fieldState: { error } }) => (
<TextField
{...field}
label="Phone Number"
error={!!error}
helperText={!!error && 'Phone or email required.'}
/>
)}
/>
<Controller
control={control}
{...register("email", {
validate: atLeastOneMediumChecked,
})}
render={({ field, fieldState: { error } }) => (
<TextField
{...field}
label="Email"
error={!!error}
helperText={!!error && 'Phone or email required.'}
/>
)}
/>
When I submit, the validation function gets called twice, once for each component. So it works the same as required: true on each one.
What I need is for the validate function to check both at once, and only return an error if both are empty.
I have tried:
function atLeastOneChecked(inputs: Inputs) {
and
function atLeastOneChecked(inputs: string[]) {
But then the validate property throws an error that the types are incompatible.
The answer to this was to use a resolver:
const { handleSubmit, control, register, formState: { errors } } = useForm<Inputs>({
defaultValues: {
...defaultValues,
},
resolver: data => {
const error: FieldErrors = {} as FieldErrors;
if (!data.phoneNumber.trim() && !data.email.trim()) {
const message = 'Either Phone Number or Email is required.';
error.phoneNumberParam = error.emailParam = { message: message, type: '' };
}
return {
values: data,
errors: error,
};
},
});