0

Having two fields in my form, that compare to each other to see if they are valid:

<input type="text" name="StartDate" id="StartDate" value="2"
       data-val="true" data-val-equalto="xx" data-val-equalto-other="EndDate"/>   
<input type="text" name="EndDate" id="EndDate" value="3"
       data-val="true" data-val-equalto="xx" data-val-equalto-other="StartDate"/> 

When I blur on StartDate, EndDate gets validated as well. So jQuery manages to avoid validation loop between one and the other.

Now, I am trying to implement the same mechanism in my custom validation rules. I get the value from the "other" field, and if everything is right, i trigger validation in the "other" as well, but this ends in a validation loop:

$.validator.addMethod("customequal-method", function (val, el, p) {
    var $other = $(el).closest('form').find('input[name=' + p.other + ']'); 
    if($other.val() == val){        
        try{$other.valid();}
        finally{return true;}
    }
    return false;
});

How could I apply the same approach than jQuery? I mean, given these two fields:

<input type="text" name="StartDate2" id="StartDate2" value="2"
       data-val="true" data-val-customequal="xx xxx" data-val-customequal-other="EndDate2"/>   
<input type="text" name="EndDate2" id="EndDate2" value="3"
       data-val="true" data-val-customequal="xx xx" data-val-customequal-other="StartDate2"/> 

I want that when modifying EndDate2, after blur, StartDate2 gets validated as well, and both became valid in the same way than in jQuery.

I have been trying to put together an example in jsFiddle, but I cannot make my custom method work: http://jsfiddle.net/vtortola/vu6tm/ ( if you find the problem I would be very grateful ), I started a separate thread about this at jQuery unobtrusive custom adapter and method in jsFiddle

Cheers.

2
  • So In your View Model, You have start date and end date, using Unobstrusive(Custom validation), you wan to validate the start date and end date. right ? Commented Jul 24, 2013 at 16:16
  • Right. This is only an example of having two fields that compare to each other. The idea is that after for example, validating StartDate2, EndDate2 gets validated as well (since it depends on StartDate2, and it has changed). Cheers. Commented Jul 24, 2013 at 17:02

1 Answer 1

1
+100

You need a stack to understand you returned back to a previously validates element. A single value is not enough because eache element may be involved in other rules with other elements. You may define the var that contains the stack in closure (isInStack verifies if the element is in the array):

(function () {
var stack = [];
$.validator.addMethod("customequal-method", function (val, el, p) {
var iAmTheRoot = stack.length == 0;
var $other = $(el).closest('form').find('input[name=' + p.other + ']'); 
if($other.val() == val){        
    try{
      if (!isInStack($other[0]) ) $other.valid();
    }
    finally{
    if (iAmTheRoot) stack = [];
    return true;}
}
return false;
});})();
Sign up to request clarification or add additional context in comments.

5 Comments

But that stack variable would be shared for all the inputs and executions that use that method? I would need to create that stack in the first invocation of the method, and then carry it through the rest of executions, but without affect other fields or rules.
No the stack is not shared by different executions and inputs, ONLY the variable containing it is shared, but this is not a problem, since javascript has no parallel threads so the variable is accessed by different groups of cooperating inputs in different time intervals. When a root input starts a validation it starts with an empty stack, after the recursive call to other validation methods returns the root input destroys the stack it used, and substitute it with an empty stack, so another input can start with an empty stack. Also if the variabke is shared no interference is possible
Any other solution would require the redefinition of the validator object methods (which is not drammatic...I do it often). A simpler solution is to apply the rule just to one of the two inputs, and managing in such a way that a change handler is attached to the second input that triggers validation on the first input each time the second input changes (I have chosen this technique to implement dynamic min and max rules connected to other inputs).
It seems to work fine. Let me test it a little bit further :)
Good approach. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.