Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 3 specifying validation trigger for Remote validation [duplicate]

I have implemented remote validation using MVC 3 unobtrusive validation as follows

The model

public class MyViewModel {
    [Remote("ValidateAction", "Validation")]
    public string Text { get; set; }
}

The Controller

public partial class ValidationController : Controller
{
    public virtual JsonResult ValidationAction(string aTextToValidate)
    {
        if(aTextToValidate == /* some condition */)
            return Json(true, JsonRequestBehavior.AllowGet);
        return Json("This is not valid, Try Again !", JsonRequestBehavior.AllowGet);
    }
}

The View

@using (Html.BeginForm() {
    @Html.TextBoxFor(m => m.Text)
    @Html.ValidationMessageFor(m => m.Text)
}

And that's it, it all works, but ValidationAction is fired on every key press, which is not ideal, I would like just to fire when the element looses focus, but cannot figure how to do this

UPDATE

Actually I have noted that, by default, the validation does fire onBlur once .i.e. the first time the element looses focus, however when attempting to correct it, validation then fires onKeyUp. I think this is intended functionality and thinking about it is probably quite useful. However it would be useful to know if it is possible to modify this behaviour

like image 671
ricardo Avatar asked Jan 25 '11 21:01

ricardo


2 Answers

Try

$.validator.setDefaults({ onkeyup: false });

It works for me.

like image 134
user678272 Avatar answered Oct 11 '22 08:10

user678272


Although I think unobtrusive validation are not made for this (the purpose is to validate input in every key press- it kind of user friendly), but there is a workaround for this approach:
You can add these very few lines(mark by //this is my code) to your jquery.validate.js and minify it OR you may create a new .js file and add the fallowing code.
Note that, if you want to get rid of onkeyup for some specific input (not for some specific rule i.e. remote) there is a specific and easy way to do that where you can find it in jquery site.
This code will only ignore remote rule for keyup event and validate others (i.e. required) normally on keyup and focuseout events.

(function ($) {
 jQuery.validator.setDefaults({
    onkeyup: function (element) {
        $(element).data('firedON', 'keyup')    //this is my code
        if (element.name in this.submitted || element == this.lastElement) {
            this.element(element);
        }
    }
});

$.validator.methods.remote = function (value, element, param) {
    if ($(element).data('firedON') == 'keyup') {
       $(element).data('firedON') = '';
       return "dependency-mismatch";           //this 'if' is my code(thats it)
    }
    if (this.optional(element))
        return "dependency-mismatch";

    var previous = this.previousValue(element);
    if (!this.settings.messages[element.name])
        this.settings.messages[element.name] = {};
    previous.originalMessage = this.settings.messages[element.name].remote;
    this.settings.messages[element.name].remote = previous.message;

    param = typeof param == "string" && { url: param} || param;

    if (previous.old !== value) {
        previous.old = value;
        var validator = this;
        this.startRequest(element);
        var data = {};
        data[element.name] = value;
        $.ajax($.extend(true, {
            url: param,
            mode: "abort",
            port: "validate" + element.name,
            dataType: "json",
            data: data,
            success: function (response) {
                validator.settings.messages[element.name].remote = previous.originalMessage;
                var valid = response === true;
                if (valid) {
                    var submitted = validator.formSubmitted;
                    validator.prepareElement(element);
                    validator.formSubmitted = submitted;
                    validator.successList.push(element);
                    validator.showErrors();
                } else {
                    var errors = {};
                    var message = (previous.message = response || validator.defaultMessage(element, "remote"));
                    errors[element.name] = $.isFunction(message) ? message(value) : message;
                    validator.showErrors(errors);
                }
                previous.valid = valid;
                validator.stopRequest(element, valid);
            }
        }, param));
        return "pending";
    } else if (this.pending[element.name]) {
        return "pending";
    }
    return previous.valid;
}
} (jQuery));  

UPDATE
The code above works for sure but I want to notice that I try to make the code more neat by not bringing whole function, ie:

var remote = $.validator.methods.remote;
$.validator.methods.remote = function(a,b,c){
   if ($(element).data('firedON') == 'keyup') return "dependency-mismatch";
   return remote(a,b,c);
}

but it failed because after storing old function in local remote variable, 'this' will referring to somewhere else, I was unable to to fix this on this code so I bring above code.

like image 26
GtEx Avatar answered Oct 11 '22 06:10

GtEx