Express-validator how to make a field required only when another field is present

10.5k views Asked by At

express-validator, how do I make a field required only when another field exists?

const validateUpdateStore = () => {
  return [
    body('logo').optional().isURL().withMessage('invalid url'),
    body('email')
      .optional()
      .isEmail()
      .withMessage('email is invalid')
      .trim()
      .escape(),
    body('phone').optional().isInt().withMessage('integers only!'),
    body('account_number').optional().isInt().withMessage('integers only!'),
    body('bank_code').optional().isInt().withMessage('integers only!'),
  ];
};

I'd like to make the field bank_code required only when account_number is provided and vise-versa

2

There are 2 answers

0
Jason Roman On BEST ANSWER

Version 6.1.0 of express-validator added support for conditional validators. I do not currently see it in the documentation but there is a pull request with more information. It looks like you should be able to define your validation as follows:

const validateUpdateStore = () => {
  return [
    body('logo').optional().isURL().withMessage('invalid url'),
    body('email')
      .optional()
      .isEmail()
      .withMessage('email is invalid')
      .trim()
      .escape(),
    body('phone').optional().isInt().withMessage('integers only!'),
    body('account_number')
      .if(body('bank_code').exists()) // if bank code provided
      .not().empty() // then account number is also required
      .isInt() // along with the rest of the validation
      .withMessage('integers only!')
    ,
    body('bank_code')
      .if(body('account_number').exists()) // if account number provided
      .not().empty() // then bank code is also required
      .isInt() // along with the rest of the validation
      .withMessage('integers only!')
    ,
  ];
};
1
ABCD.ca On

To add to @Jason's answer here's how you can conditionally validate one field based on the value of another when the objects are in an array and you're using wildcard syntax:

// only validate `target` if `requiresTarget` is true
body('people[*].weight')
  .if((value, { req, location, path }) => {

    /*
      Gets numeric, index value of "*". Adjust your regex as needed
      if nested data uses more than one wildcard
    */
    const wildcardIndex = parseInt(path.match(/([0-9]+)/)[1])

    // return a true value if you want the validation chain to proceed.
    // return false value if you want the remainder of the validation chain to be ignored
    return req.body.people[wildcardIndex].requiresWeight
  })
  .isFloat() // only applies this if `requiresWeight` is true
  .withMessage('weight must be float'),