Search code examples
javascriptreactjsreact-hook-form

Validation of react-hook-form form with one or more values in a set of input fields


There is a set of textfields in a react-hook-form form. Of course I can set a field as required.

<Controller
  control={control}
  name="value1"
  rules={{ required: true }}
  render={({ field }) => (
    <TextField
      {...field}
      fullWidth
      sx={{ maxWidth: 600 }}
      label="Value 1"
      margin="dense"
    />
  )}
/>

But in my case the form is valid, if one or more fields have a value. How do I check for "one or more" input values?


Solution

  • To validate that at least one field in the form you have has a value you can create a custom function for validation with in the rules prop of the react-hook-form For example:

    const FormDemo = () => {
      const { handleSubmit, control, getValues } = useForm();
    
      const onSubmit = (data) => {
        console.log('Form Submitted: ', data);
      };
    
      const validateValues = (value) => {
        const values = getValues();
        return (
          values.value1 ||
          values.value2 ||
          values.value3 ||
          'At least one field is required.'
        );
      };
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <Controller
            control={control}
            name="value1"
            rules={{
              validate: validateValues,
            }}
            render={({ field, fieldState }) => (
              <TextField
                {...field}
                fullWidth
                sx={{ maxWidth: 600 }}
                label="Value 1"
                margin="dense"
                error={!!fieldState.error}
                helperText={fieldState.error ? fieldState.error.message : ''}
              />
            )}
          />
          <Controller
            control={control}
            name="value2"
            rules={{
              validate: validateValues,
            }}
            render={({ field, fieldState }) => (
              <TextField
                {...field}
                fullWidth
                sx={{ maxWidth: 600 }}
                label="Value 2"
                margin="dense"
                error={!!fieldState.error}
                helperText={fieldState.error ? fieldState.error.message : ''}
              />
            )}
          />
          <Controller
            control={control}
            name="value3"
            rules={{
              validate: validateValues,
            }}
            render={({ field, fieldState }) => (
              <TextField
                {...field}
                fullWidth
                sx={{ maxWidth: 600 }}
                label="Value 3"
                margin="dense"
                error={!!fieldState.error}
                helperText={fieldState.error ? fieldState.error.message : ''}
              />
            )}
          />
          <Button type="submit" variant="contained" color="primary">
            Submit
          </Button>
        </form>
      );
    };
    
    export default FormDemo;
    
    1. The Custom Function: This function will check if any of the field has a value, in case none of the field has any value it would return an error message
    2. getValues(): This is a helper function from the react-hook-form that retrieves the current value of all the fields, which we can then use to determine if the field has been filled out or not

    This approach should give you the desired behavior