Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate with Yup that in array of objects at least one of object keys has true value?

I have a form with dynamical fields (answers). I'm using Formik and Yup for validations. One answer is object {text: string, is_correct: boolean}. I need to make validation schema that at least one answer should have is_correct: true How to make validation in this case?

function answersSchema (rules) {
    const {
        QUIZ_ANSWER_MAX_LENGTH,
        QUIZ_ANSWER_MIN_LENGTH,
    } = rules;
    return Yup.object().shape({
        text: Yup.string()
            .min(QUIZ_ANSWER_MIN_LENGTH, 'Too Short!')
            .max(QUIZ_ANSWER_MAX_LENGTH, 'Too Long!').required('Text of answer is required'),
        is_correct: Yup.boolean().required()
    })
}

export function setQuizSchema(rules) {
    const {
        QUIZ_QUESTION_MAX_LENGTH,
        QUIZ_QUESTION_MIN_LENGTH,
        QUIZ_DESCRIPTION_MAX_LENGTH,
        QUIZ_DESCRIPTION_MIN_LENGTH,
        QUIZ_MAX_COUNT_OF_ANSWERS,
        QUIZ_MIN_COUNT_OF_ANSWERS,
    } = rules;
    return Yup.object().shape({
        question: Yup.string()
            .min(QUIZ_QUESTION_MIN_LENGTH, 'Too Short!')
            .max(QUIZ_QUESTION_MAX_LENGTH, 'Too Long!')
            .required('Required'),
        description: Yup.string()
            .min(QUIZ_DESCRIPTION_MAX_LENGTH, 'Too Short!')
            .max(QUIZ_DESCRIPTION_MIN_LENGTH, 'Too Long!'),
        answers: Yup.array().of(answersSchema(rules))
            .min(QUIZ_MIN_COUNT_OF_ANSWERS, `The quiz should have a minimum of ${QUIZ_MIN_COUNT_OF_ANSWERS} answers`)
            .max(QUIZ_MAX_COUNT_OF_ANSWERS, `The quiz should have a maximum of ${QUIZ_MAX_COUNT_OF_ANSWERS} answers`)
    })
}
like image 673
Anna Logacheva Avatar asked Jul 16 '20 09:07

Anna Logacheva


1 Answers

You could use the test method on yup schema, so your code could be something like this

...
return Yup.object().shape({
        question: Yup.string()
            .min(QUIZ_QUESTION_MIN_LENGTH, 'Too Short!')
            .max(QUIZ_QUESTION_MAX_LENGTH, 'Too Long!')
            .required('Required'),
        description: Yup.string()
            .min(QUIZ_DESCRIPTION_MAX_LENGTH, 'Too Short!')
            .max(QUIZ_DESCRIPTION_MIN_LENGTH, 'Too Long!'),
        answers: Yup.array().of(answersSchema(rules))
            .min(QUIZ_MIN_COUNT_OF_ANSWERS, `The quiz should have a minimum of ${QUIZ_MIN_COUNT_OF_ANSWERS} answers`)
            .max(QUIZ_MAX_COUNT_OF_ANSWERS, `The quiz should have a maximum of ${QUIZ_MAX_COUNT_OF_ANSWERS} answers`)
            .test('test-name', 'custom error message', answers => {
                return answers.some(answer => answer.is_correct)
             })
    })
    

as a side note, it is better to use const for declarations that wont change like the variable declarations in the answersSchema function.

like image 164
ehab Avatar answered Oct 26 '22 23:10

ehab