Validation for array of fields using react hook form

16.1k Views Asked by At

I want to add validation to the input fields. I am using react hook form. The validation should be like the sum of the fields should be 100. If any of the fields make the sum more or lesser than 100, it should show an error at the input field (the last edited one).

sandbox url: https://codesandbox.io/s/distracted-elion-z2wob?file=/src/App.js

thanks

4

There are 4 best solutions below

0
On

why don't you use ranges ?? you can set min to 0 and max 100-current, this would prevent user to set any value above 100. About values under a 100 you could check manually.


<input type="range" min="0" max={100-currentTotal} step={1}/>
{currentTotal< 100 && lastEdited? "error the sum should be equal to 100" : null}
// I used 1 as the step, but you can set any value


0
On

this handleSubmit function will get all your fields, get your values, add them and provide you with the total. You can handle the error in the if-else statement.

 const handleOnSubmit = (form) => {
       console.log('form fields', form.questions)
       let data = form.questions.map( x => x.percentage ).reduce((a,b) => a + b);

      if ( data !== 100) {
        console.log('total', data , ' is not 100');
        //error handling here.
      }
       
  };

sandbox

react-use-form error handling <- Error handling codes and example here.

2
On

You just need to use Yup's test() method to validate the total:

resolver: yupResolver(
  object().shape({
    questions: array()
      .of(
        object().shape({
          percentage: number().typeError('Wrong type.').required('Required.')
        })
      )
      .required()
      .test(
        'sum',
        'The total should be less or equal than 100.',
        (questions = []) => {
          const total = questions.reduce((total, question) => {
            return total + (question.percentage || 0);
          }, 0);

          return total <= 100;
        }
      )
  })
),

If that validation fails, the errors object will look like this:

{
  "questions": {
    "message": "The total should be less or equal than 100.",
    "type": "sum"
  }
}

You can then display the error with { errors.questions?.message }.

0
On

There's a recent new feature in react-hook-form v7.34.0 that provides this kind of validation out of the box...

You set it up when you define the field array

In your case, you could run the check for sum of fields == 100 inside a custom validation function

useFieldArray({
  name: 'test',
  rules: {
    validate: (fieldArrayValues) => {
      // check that sum of all fields == 100
    },
  }
})

And then you check for/use the error as such

errors?.test?.root?.message

See here for further details...

https://react-hook-form.com/api/usefieldarray/

https://github.com/react-hook-form/react-hook-form/issues/6879

https://github.com/react-hook-form/react-hook-form/pull/8562