0

To give an example, how can I define a field that can be blank OR digits OR "foo" ?

I currently have this:

var myValidator= jQuery2("#myFormId").validate({
    rules: {
        myField: {
            digits: true,
            required: false,
            maxlength: 9999,
            myCustomRule: true
        }
}});
jQuery2.validator.addMethod("myCustomRule", function(value, element) {
    return value === "foo" || value=="";
}, "myMessage");

However, jQuery Validation Plugin automagically applies an AND logical operator between requirements, how can I have an OR ? (or have my custom method call jQuery Validation Plugin built-in rules like digits ? I'm not javascript guru, maybe that's obvious looking at the source ?)

Toto
  • 397
  • 6
  • 17
  • Your code does work here. However you want `myField` to be digit only, but you try to validate it against `"foo"` ? – Serge K. Jan 05 '18 at 10:00
  • What do you want in the end ? The value of `myField` should be equal to what or what ? – Serge K. Jan 05 '18 at 10:09
  • I think I couldn't edit my previous comment so I have just deleted it. Below is an updated copy. jQuery Validation Plugin evaluates the following [(digits: true, required: false, maxlength: 9999) AND myCustomRule]. What I want is [(digits: true, required: false, maxlength: 9999) OR myCustomRule]. PS. is it not possible to use formatting (code, BRs...) in comments ? – Toto Jan 05 '18 at 10:09
  • In fact, your comment **is** edited. It is possible to use formatting, take a look a the help link under the `Add Comment` button. Also, _What do you want in the end ? The value of myField should be equal to what or what ?_ – Serge K. Jan 05 '18 at 10:12
  • Following the example in the OP, if the code did what I want, the user should be able to input "", 9999999, "foo". "faa", any input longer than 10,000 characters, -12 are all invalid. – Toto Jan 05 '18 at 10:34
  • You're going to have another issue after solving this one. Even though `required` is set to `false`, your custom rule will still be triggered when the field is left blank. See: https://stackoverflow.com/a/29754190/594235 – Sparky Jan 06 '18 at 16:23

2 Answers2

2

Title: ... custom logical operators (=> rule1 OR rule2 OR rule3…)

When you declare rules for this plugin, it will apply ALL rules that are declared using a logical AND.

rules: {
    myField: {
        digits: true,
        //required: false, // <- 'false' is superfluous/default
        maxlength: 9999,
        myCustomRule: true
    }
}

The above states that this field must satisfy digits AND maxlength AND myCustomRule; AND it will not be required if myCustomRule is properly written.

There is no option within this plugin to change "AND" into "OR" when evaluating the list of declared rules.

The only way you can evaluate the rules using an OR operator is by creating a single custom rule that encompasses all of your validation logic into one function.

rules: {
    myField: {
        myCustomRule: true
    }
}

Where myCustomRule contains your own function with all rule logic separated by OR operators. See below for the solution to your exact example.

... how can I define a field that can be blank OR digits OR "foo" ?

You must create a custom rule that does all three within one function.

  • blank: This is considered "optional" and when you create your own custom rule, it will not allow the field to remain blank unless you compare the result to this.optional(element) using an OR operator.

  • "foo": Use value === "foo"

  • digits: Just use the code for the existing digits rule, /^\d+$/.test(value)

Then string it all together using OR operators...

$.validator.addMethod("myCustomRule", function(value, element) {
    return this.optional(element) || value === "foo" || /^\d+$/.test(value);
}, "myMessage");

Everything is contained within this new custom rule, so you must not declare any other rules...

var myValidator = $("#myFormId").validate({
    rules: {
        myField: {
            myCustomRule: true
        }
    }
});

The result is an "optional" field that will also validate for digits or the string "foo".

DEMO: jsfiddle.net/tLoef0ov/

Sparky
  • 98,165
  • 25
  • 199
  • 285
  • You missed the length part. – Serge K. Jan 09 '18 at 08:47
  • @SergeK., I did not. I answered the question exactly how it was asked, *“how can I define a field that can be blank OR digits OR "foo" ?“* The OP’s mistake was that his example code did not match his question. – Sparky Jan 09 '18 at 13:23
  • Didn't want to be rude, sorry :/ I was just pointing out what I thought was missing – Serge K. Jan 09 '18 at 15:23
  • I can't accept two answers so I have accepted the first answer (as I said I would instead of this one). Thanks for the more throughout answer, though. Apologies about the example not matching 100% the question (title). I understand this is a big source of confusion so I will take more care with it next time. – Toto Jan 09 '18 at 16:41
  • 1
    @Toto, it is solely up to you to choose whichever answer you see fit. Just keep in mind that you are supposed to choose what you believe to be the “best” answer, not necessarily the “first” answer, as this process of acceptance is ideally meant for helping the community of future readers. – Sparky Jan 09 '18 at 18:57
1

Here is how to do it. You cannot use digits: true in your case since you want it to be either a number or "foo".

var myValidator = $("#myFormId").validate({
  rules: {
    myField: {
      required: false,
      maxlength: 9,
      myCustomRule: true
    }
  }
});

$.validator.addMethod("myCustomRule", function(value, element) {
  return value === "" || value === "foo" || !isNaN(value);
}, "myMessage");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"></script>
<form id="myFormId">
  <input type="text" name="myField" />
</form>
Serge K.
  • 5,303
  • 1
  • 20
  • 27
  • This would work, thanks, but if possible I'm looking for a generic answer. You used isNaN instead of the exact same logic as implement by jQuery for 'digits'. What if I used dateISO or rangelength, for instance? Does a solution to this issue *has* to be 100% specific in that it *cannot* reuse on jQuery Validation Plugin existing rules ? – Toto Jan 05 '18 at 10:38
  • I can't find any option in the documentation telling jQuery Validate plugin to apply a logical OR between rules, so I guess this is the only way to go. – Serge K. Jan 05 '18 at 10:53
  • What about calling jQuery Validation Plugin rules underlying logic from my own code ? "methods" are defined in jquery.validate.js source. I can see 'required', 'email' etc. all defined there, maybe there is a clean way to callit ? (as I said I'm no javascript guru). There is also the standard addMethod (which I use in my example), surely there should be something like a getMethod method ? – Toto Jan 05 '18 at 11:01
  • I have tried calling jQuery2.validator.methods.digits(value, element) from my custom rule, btw, but it crashes jQuery Validation Plugin ( TypeError: this.optional is not a function, jquery.validate.js:1041:11) – Toto Jan 05 '18 at 11:08
  • 1
    I think you'll need to use `apply` or `bind` (look them up on MDN) to use this function, otherwise you use it outside of its context (implying the error you're getting) but that's outside the scope of this question. IMO it is perfectly fine to use `isNaN` here. – Serge K. Jan 05 '18 at 11:18
  • You have answered the issue related to the specific example in the OP (thank you for that, but it is just that, an example), not the general question as specified in the title. Unless that is really contrary to Stack Exchange etiquette, I would rather not make your answer an accepted answer. If that is bad etiquette then no problem, just tell, I will accept your answer and ask again in a new question. – Toto Jan 05 '18 at 11:29
  • 1
    This not really bad etiquette, you can decide my answer isn't the one you are waiting for :). BUT I'm _not_ sure there is any other way to do it. – Serge K. Jan 05 '18 at 12:57
  • In your final code, the maxlength rule is going to be evaluated against the custom rule using a logical AND operator, not quite what the OP was asking for. – Sparky Jan 09 '18 at 13:27