Search code examples
node.jsvalidationdependenciesjoi

joi custom validation depending on other field's data


I am trying to create a custom validation rule (using the JOI validations library in a node.js application) that dependent of other fields of the form.

For example: I need the username field to be required if both of the email or mobile fields are empty or visa versa.

I have already tried the when and or methods, provided by the library itself and searched on the google as well. But, still standing on same place.

When example:

const validations = joi.object({
    ...
    username: joi.any().when('email', {
        is: '' || null || undefined,
        then: joi.required()
    }),
    email: joi.any().optional(),
    mobile: joi.any().optional(),
    ...
}).options({
    abortEarly: false
});

Or Example:

const validations = joi.object({
    ...
    username: joi.any(),
    email: joi.any(),
    mobile: joi.any(),
    ...
}).or('username', 'email', 'mobile').options({
    abortEarly: false
});

Please help, this issue has already cost me too much time.


Solution

  • Here is my working code:

    Reference: How to add custom validator function in Joi?

    export default (req, res, next) => {
        const validations = joi.object({
            ...
            email: joi.any().custom((value, helper) => {
                if (! value && ! req.body.username && ! req.body.mobile) {
                    return helper.message('Required field');
                }
    
                return true;
            }),
            mobile: joi.any().custom((value, helper) => {
                if (! value && ! req.body.username && ! req.body.email) {
                    return helper.message('Required field');
                }
    
                return true;
            }),
            username: joi.any().custom((value, helper) => {
                if (! value && ! req.body.email && ! req.body.mobile) {
                    return helper.message('Required field');
                }
    
                return true;
            }),
            ...
        }).options({
            abortEarly: false
        });
    
        const { error } = validations.validate({
            ...
            email: body.email ? body.email : null,
            mobile: body.mobile ? body.mobile : null,
            username: body.username ? body.username : null,
            ...
        });
    
        if (error) {
            return res.status(406).send({ ... });
        }
    
        next();
    }
    

    I hope this can help someone, facing the situation like this.