Home > other >  Checking value of drop down is not in another drop down. Custom Validation using YUP
Checking value of drop down is not in another drop down. Custom Validation using YUP

Time:11-02

Im have 3 drop downs in a React Formik form, each with the same set of options. I want to provide some custom validation using YUP to ensure that each of these drop downs has a unique value selected.

The Formik values being set on each field take the shape of {id: somevalue, text: someText }

I have tried setting up my validation object as below:

const { values } = useFormikContext();

const validation = Yup.object({
    picker1: Yup.object()
        .test('test-name', 'Value must be Unique',
            function (value) {
                 return !((values["picker2"] && values["picker2"].id === value.id) ||
                (values["picker3"] && values["picker3"].id === value.id));
            }),
        ... repeat for other pickers
})

The problem I am having is that the formik value is always null for the pickers when the test function executes, presumably because the value of values is scoped to when the function is created. Is there a better way of attempting this as the documentation around custom validation in YUP seems a bit sparse.

CodePudding user response:

So I managed to work out how to do this without using the Formik context and instead using the using the Yup object inside its test method.

const validation = Yup.object(){
    picker1: Yup.object()
        .shape({
            id: Yup.string().required(),
            text: Yup.string().required()
        })
        .nullable()
        .test(
            'unique-values',
            'Selected picker values must all be different',
            (data, { parent }) => {
                return (
                    data
                    && (parent.picker2 == null || (parent.picker2 != null && data.id !== parent.picker2.id))
                    && (parent.picker3 == null || (parent.picker3 != null && data.id !== parent.picker3.id))
                )
            }
        ),
    picker2: Yup.object()
        .shape({
            id: Yup.string().required(),
            text: Yup.string().required()
        })
        .nullable()
        .test(
            'unique-values',
            'Selected picker values must all be different',
            (data, { parent }) => {
                return (
                    data
                    && (parent.picker1 == null || (parent.picker1 != null && data.id !== parent.picker1.id))
                    && (parent.picker3 == null || (parent.picker3 != null && data.id !== parent.picker3.id))
                
            }
        ),
    picker3: Yup.object()
        .shape({
            id: Yup.string().required(),
            text: Yup.string().required()
        })
        .nullable()
        .test(
            'unique-values',
            'Selected picker values must all be different',
            (data, { parent }) => {
                return (
                    data
                    && (parent.picker1 == null || (parent.picker1 != null && data.id !== parent.picker1.value))
                    && (parent.picker2 == null || (parent.picker2 != null && data.id !== parent.picker2.id))
                )
            }
        )
};

Obviously quite a lot of replicated code in there and its not the most elegant. Would be very interested in any other solutions.

  • Related