2

I'm trying to validate an input using jquery validator 'addMethod'. The main goal is to check if the current user id exists in the system and if it does a error message is displayed. To check if the user exists I make a ajax call to my controller and it returns true or false.

$("input[name='VATNumber']").blur(function () {

        var tbody = $(this).showLoading();

        var vatnumber = $(this).val();

        var svcUrl = "@Url.Action("CheckUserExistance", "User")";

        $.ajax({
            url: svcUrl + "?vatNumber=" + vatnumber,
            type: "GET",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            async: true,
            cache: true,
            error: function (xhr, err) {
                tbody.hideLoading();
                $.jGrowl("ERROR checking user.", { life: 5000, group: "error" });
            },
            success: function (result) {
                tbody.hideLoading();
                displayErrorMessage(result.data);

                //console.log(result);
                //if (result.data == false) { displayErrorMessage(); }
            }
        });

        function displayErrorMessage(result) {
            console.log(result);
            jQuery.validator.addMethod("checkUser", function (value) {
                return result == false;
            }, "User already exists.");

            jQuery.validator.classRuleSettings.checkUser = { checkUser: true };

            $("input[name='VATNumber']").validate();
        }

    });

The problem is that the validator is not displaying the message at the right time, even so the 'result' variable is right.

Can someone help, please?

UPDATE

I've tried with this code and it still doesn't work. The request is not considered.

var vatnumber = $("input[name = 'VATNumber']").val(),
        officeid = parseInt($("input[name='OfficeID']").val(), 10);
var svcUrl = "@Url.Action("CheckUserExistance", "User")";

    $('#mainForm').validate({
        rules: {
            VATNumber: {
                required: true,
                VATNumber: true,
                remote: {
                    url: svcUrl,
                    type: "post",
                    data: {
                        vatNumber: vatnumber,
                        officeId: officeid
                    }
                }
            }
        },
        messages: {
            VATNumber:  {
                remote: "User already exists."
            }
        }
    });

I'm using ASP.NET MVC and Bootstrap

HTML

    <div class="par control-group">
                    <label class="control-label" for="VATNumber">NIF</label>
                    <div class="controls">

<input class="input-large" data-val="true" data-val-maxlength="MaxLengthAttribute" data-val-maxlength-max="50" id="VATNumber" name="VATNumber" type="text" value="2345678">
                        <span class="field-validation-valid" data-valmsg-for="VATNumber" data-valmsg-replace="true"></span>
                    </div>
                </div>

SCRIPT

$(document).ready(function () {

    //$("input[name='VATNumber']").addClass("checkUser");

    var vatnumber = $("input[name = 'VATNumber']").val(),
        officeid = parseInt($("input[name='OfficeID']").val(), 10);

    var svcUrl = "@Url.Action("CheckUserExistance", "User")";

    console.log(svcUrl + " " + vatnumber);

    $('#mainForm').validate({
        rules: {
            VATNumber: {
                required: true,
                remote: {
                    url: svcUrl,
                    type: "post",
                    // for troubleshooting
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        console.log('status: ' + textStatus); // status
                        console.log('error: ' + errorThrown); // error
                    },
                    complete: function (jqXHR, textStatus) {
                        // fires after the request, even if there is an error
                        console.log('ajax is finished: ' + textStatus);
                    }
                }
            }
        },
        messages: {
            VATNumber: {
                remote: "User already exists."
            }
        }
    });
});
xatz
  • 425
  • 1
  • 6
  • 14
  • Regarding your edit: you declared a rule called `VATNumber: true`. There is no such rule called `VATNumber`, so this is the point where it fails, before it even reaches the `remote` method. Also, not a big deal, but `vatNumber: vatnumber` is not needed inside `data` option. The value of the field itself is already sent by default. – Sparky Mar 25 '15 at 14:47

2 Answers2

3

Your code...

$("input[name='VATNumber']").blur(function () {

    ....

    $.ajax({
        ....
    });

    function displayErrorMessage(result) {

        jQuery.validator.addMethod("checkUser", function (value) {
            return result == false;
        }, "User already exists.");

        jQuery.validator.classRuleSettings.checkUser = { checkUser: true };

        $("input[name='VATNumber']").validate();
    }

});

Problems:

  1. Everything is inside a blur handler. I'm not sure why you need this when the jQuery Validate plugin already uses a focusout handler by default. You can eliminate the blur() handler entirely.

  2. You've attached the .validate() method to an input. You cannot do this. The .validate() method only gets attached to the <form> element.

  3. You've put the .validate() method inside of a displayErrorMessage function which is nested inside your blur handler function. However, the .validate() method is used for initializing the plugin on your form and should be called once and only on DOM ready.

  4. You've also put .addMethod() inside of a displayErrorMessage function which is nested inside your blur handler function. However, the .addMethod() method is used for creating/initializing the new rule and should be called once and only on DOM ready. In this case, your new rule/method does not appear to be used anywhere, not needed, and not even properly constructed.

  5. Your .ajax() is completely independent of the jQuery Validate plugin. However, the plugin already contains an ajax method called remote, where its sole function is to remotely check with the server; to check if a username already exists, for example.

"The main goal is to check if the current user id exists in the system and if it does a error message is displayed."

Then you don't even need the .ajax() or the .addMethod() method at all. Simply properly implement the remote rule/method.

$(document).ready(function() {

    $('#myform').validate({
        rules: {
            VATNumber: {
                required: true,
                remote: {
                    // your other options
                }
            }
        }
    });

});

Your server-side code can return a true or false indicating pass or fail validation. Alternatively, if you return a JSON encoded string, then it fails validation and the JSON string automatically becomes the validation message.

Also see: jQuery Validate remote method usage to check if username already exists


EDIT:

Based on edited OP and his comments...

$(document).ready(function() {  // <-- everything inside a DOM ready handler?

    $('#mainForm').validate({  // <-- 'mainForm' is ID of your <form></form>?
        rules: {
            VATNumber: {
                required: true,
                // VATNumber: true, // <-- NO SUCH METHOD/RULE
                remote: {
                    url: svcUrl, // <-- positively verify the URL
                    type: "post",
                    data: {
                        vatNumber: vatnumber,  // <-- redundant
                        officeId: officeid
                    },
                    // for troubleshooting
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        console.log('status: ' + textStatus); // status
                        console.log('error: ' + errorThrown); // error
                    },
                    complete: function(jqXHR, textStatus) {
                        // fires after the request, even if there is an error
                        console.log('ajax is finished: ' + textStatus);
                    }
                }
            }
        },
        ....
    });

});
Community
  • 1
  • 1
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Thank you so much @Sparky ! After some research I found the remote function. I'm considering all the problems you've listed and I'll give you some feedback right after I solve this. – xatz Mar 25 '15 at 09:42
  • I'm having trouble calling my action method. – xatz Mar 25 '15 at 11:24
  • @xatz, you declared a non-existant rule called `VATNumber` inside `VATNumber`. This stops validation before it reaches the `remote` method. You should be getting a console error about an "undefined method" because of this. – Sparky Mar 25 '15 at 14:50
  • I don't get any error which is weird and I've tried without that rule and still doesn't work :( – xatz Mar 25 '15 at 14:58
  • @xatz, I know that if you put a non-existent rule into the list, it stops cold at at that point. Carefully check your syntax and look at my edits. Use your console for troubleshooting... it will also give you useful information about the server response codes from the `remote` method's `ajax` request. Inspect your DOM to verify that the URL for your `remote` method is correct. – Sparky Mar 25 '15 at 15:03
  • I tested everything and still can't get an error at the console and the method doesn't get hit. – xatz Mar 25 '15 at 15:59
  • @xatz, are you sure the URL is being constructed correctly? Inspect your DOM and verify this. Thousands of websites, including my own, are using the `remote` method without any problems. I'm not sure what else I can tell you. You can also try putting some `console.log` lines into the options to see what you get. See my edits. – Sparky Mar 25 '15 at 16:41
  • unfortunately nothing is being written at the console. The URL is constructed correctly and the DOM exists. The rule is just not being considered. :( – xatz Mar 25 '15 at 16:56
  • @xatz, for the code you've shown, that does not make any sense at all. Does the `required` rule work? – Sparky Mar 25 '15 at 17:01
  • @xatz, you should have mentioned that minor detail! If the `required` rule isn't working either, then something is breaking the entire plugin. Is your `.validate()` method wrapped in a DOM ready handler? Is your `.validate()` method properly attached to your `form`? You did not show us any HTML whatsoever, so it's impossible for me to know. – Sparky Mar 25 '15 at 17:34
  • Sorry @Sparky but as it worked with the first code I thought it was supposed to work correctly. I'll edit my original post. – xatz Mar 25 '15 at 17:42
  • @xatz, JavaScript does not care about your framework, so only show the ***rendered*** HTML as seen by the browser. Also, if you're using ASP, then make sure you're NOT using the `unobtrusive-validation` plugin as this calls its own instance of `.validate()` thus totally negating yours. – Sparky Mar 25 '15 at 18:20
  • @xatz, I can't see any `form` tags so I just have to assume they're correct? However, your `input` for `VATNumber` already has a `value` so of course the `required` rule is never going to fire. Just make sure you don't have `unobtrusive-validation` installed. Otherwise, I'm out of ideas. – Sparky Mar 25 '15 at 18:35
  • Thanks for all your effort helping me @Sparky. I turned false the UnobtrusiveJavaScript key at Web.config to try if the remote method was called and didn't get any luck. Running out of ideas as well :( – xatz Mar 26 '15 at 11:39
2

Despite all the help from @Sparky (thank you so much) and after running out of ideas, I talked to a friend and he said to try calling the ajax inside the addMethod. And it worked better than the first attempt. So here it is:

$(document).ready(function () {

    $("input[name='VATNumber']").addClass("checkUser");

    var vatnumber = $("input[name = 'VATNumber']").val(),
        officeid = parseInt($("input[name='OfficeID']").val(), 10);

    var svcUrl = "@Url.Action("CheckUserExistance", "User")";

    jQuery.validator.addMethod("checkUser", function (value, element) {
        var exists = false;
        $.ajax({
            url: svcUrl + "?vatNumber=" + value
                        + "&officeId=" + officeid,
            type: "GET",
            async: false,
            cache: false,
            error: function (xhr, err) {
                $.jGrowl("ERROR checking user.", { life: 5000, group: "error" });
            },
            success: function (result) {
                exists = result;
            }
        });
        return exists;
    }, "User already exists.");
    //});

    jQuery.validator.classRuleSettings.checkUser = { required: true, checkUser: true };
});
xatz
  • 425
  • 1
  • 6
  • 14