5

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 🙏

1
  • thanks for the sandbox but you where is your attempt in handleSubmit? can you use const handleSubmit = (form) => { console.log('form', form.questions) } to see the values, you can add them up then display error if more or less than 100. Commented Nov 27, 2020 at 18:09

4 Answers 4

7

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

Sign up to request clarification or add additional context in comments.

Comments

0

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


Comments

0

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.

Comments

0

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 }.

2 Comments

codesandbox.io/s/lingering-shadow-0cxxo?file=/src/App.js the same approach, but the errors are not showing properly.. can you have a look?
It looks like the validation is actually running and removing the error, but react-hook-form's error object is not. I suspect this has to do with render isolation, but somehow it's not properly checking for updates on Yup's errors object. Maybe you should open an issue on react-hook-form.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.