validatorjs icon indicating copy to clipboard operation
validatorjs copied to clipboard

Wrong behaviour with `min` and empty array

Open danilopolani opened this issue 5 years ago • 3 comments

This is probably related to: https://github.com/skaterdav85/validatorjs/issues/215

If you try to validate an empty array with the min rule, it passes instead of returning error. Doing some reverse eng. it seems the problem is inside isValidatable, like that issue above said. This is an example code:

      const validation = new Validator({
        images: []
      }, {
        'images': 'array|min:5'
      })
      console.log('Passes?', validation.passes()) // true
      console.log(validation.errors.all()) // {}

Probably partial related to https://github.com/skaterdav85/validatorjs/issues/242. Adding a required in front of the rules solves this, but it's not the correct behaviour: for example, I want the min error, not the required, since the min includes, by logic, also the required one.

Another small issue: the default message for min with arrays is wrong: currently returns The images must be at least 5 characters. but of course it does not make sense.

danilopolani avatar Jan 13 '20 14:01 danilopolani

I encountered a similar issue trying to create a custom validator to require a minimum length for an array field based on the state of another field. The docs don't really explain it but within the rules.js file in the source there are a set of rules that are in a set referred to as implicit rules. This set includes the various 'required' rules as well as 'accepted' and 'present'. Implicit here means implicitly required, i.e. the rule will fail if the field is not present rather than the standard behavior to pass.

To make the min rule validate empty arrays properly, you need to create an implicit custom validator. Mine looks like this:

Validator.registerImplicit(
  'has_items',
  function (value, req, attribute) {
    req = this.getParameters();
    if (
      this.validator._objectPath(this.validator.input, req[0]) ===
      (req[1] === 'true')
    ) {
      return value.length >= 1;
    }
    return true;
  },
  ':attribute must contain at least one item',
);

Bear in mind that this function is to validate a minimum length of 1 based on another field being true, so a slightly more complex use case than what was originally asked in this issue.

this.getParameters and this._objectPath are both functions within the package's source that weren't mentioned in the docs. Again, I had to dig through the source manually to figure out how this thing actually works.

Pmurs avatar Aug 05 '20 03:08 Pmurs

I think this is not an issue, maybe I'm not understanding it but the documentation states: "Validation rules do not have an implicit 'required'." Am I missing something?

jrobinsonc avatar Jun 05 '21 01:06 jrobinsonc

I expected something like required|array|min:2|max:2 or required|array|size:2 to constrain the array size but it does not seem to have that effect.

steveoh avatar Dec 19 '22 01:12 steveoh