Dynamically changing jQuery unobtrusive validation attributes

asp.net-mvc-4, jquery-validate, unobtrusive-validation

Solution

As Sparky pointed out changing default attributes dynamically will not be picked up after the validation plugin has been initialized. To best work around this without rewiring how we register validated fields and rules, I found it easiest to register a custom adapter in the unobtrusive library:

jQuery.validator.unobtrusive.adapters.add("amount", {}, function (options) {
  options.rules["amount"] = true;
  options.messages["amount"] = function () { return $(options.element).attr('data-val-amount'); };
});

jQuery.validator.addMethod("amount", function (val, el, params) {    
  try {
    var max = $(el).attr('data-amount-max');
    var min = $(el).attr('data-amount-min');
    return val <= max && val >= min;
  } catch (e) {
    console.log("Attribute data-amount-max or data-amount-min missing from input");
    return false;
  }
});

Because the message is a function, it will be evaluated every time and always pick up the latest attribute value for `data-val-amount`. The downside to this solution is that everytime there is a change we need to change all three attributes on the input: `data-amount-min`, `data-amount-max`, and `data-val-amount`.

Finally here is the input markup on initial load. The only attribute that needs to be present on load is data-val-amount.

<input id="amount" data-val-amount="Please enter an amount between ${0} and ${1}" data-val="true">

Problem

I have a page built in ASP.NET MVC 4 that uses the jquery.validate.unobtrusive library for client side validation. There is an input that needs to be within a range of numbers. However, this range can change dynamically based on user interactions with other parts of the form. The defaults validate just fine, however after updating the `data-rule-range` attribute, the validation and message are still triggered on the original values. Here is the input on initial page load: ``` <input id="amount" data-rule-range="[1,350]" data-msg-range="Please enter an amount between ${0} and ${1}"> ``` This validates correctly with the message `Please enter an amount between $1 and $350` if a number greater than 350 is entered. After an event fires elsewhere, the `data-rule-range` is updated and the element looks as such: ``` <input id="amount" data-rule-range="[1,600]" data-msg-range="Please enter an amount between ${0} and ${1}"> ``` At this point if 500 is entered into the input it will fail validation with the same previous message stating it must be between $1 and $350. I have also tried removing the validator and unobtrusiveValidation from the form and parsing it again with no luck. ``` $('form').removeData('validator'); $("form").removeData("unobtrusiveValidation"); $.validator.unobtrusive.parse("form"); ``` Is there a clean way to change the validation behavior based on the input attributes dynamically?

Original source