brentonstrine
brentonstrine

Reputation: 22742

Error response from jQuery Validate remote isn't working

I am using the remote method of jQuery Validation to check if a username already exists in the system. The script does_user_exist.php returns 1 if the user exists.

$registration.find(".username").each(function() {
    var $this = $(this);
    $this.rules('add', {
        remote: {
            url: "does_user_exist.php",
            type: "post",
            dataType: "json",
            data: {uname: function(){ return $this.val(); } },
            async: false,
            success: function (data) { //returns 1 if user exists
                if (data) {
                   console.log("false!");
                   return "Sorry, that user already exists." //doesn't work
                   //return false;        //doesn't work
                   //return data;         //doesn't work
                   //return {"string"};   //doesn't work
                   //return {0: "string"};//doesn't work
                } else {
                   console.log("true!");
                   return true;
                }
            }
        },
        messages: {
            remote: jQuery.format("{0}") //doesn't work
            // remote: "Simple string doesn't work here either"
        }
    });
});

My problem is that the error message is never displayed. I can see from my console.log output that it correctly logs false! when the user exists, but the error message never shows up.

As you can see from the commented out lines, I've been trying to figure out what exactly I'm doing wrong via guess-and-check, on the assumption that I'm somehow returning the error string in the wrong format, but I'm not having success.

Edit3: I was able to get the backend response to be changed. The PHP is now sending JSON encoded true/false, to no avail. We have tried sending the backend response in the following ways, but the plugin doesn't seem to be catching it no matter what we do:

json_encode( false )
json_encode( '["false"]' )
json_encode( "false" )
json_encode( ["false"] )
"false"
false
NULL
""
0

As far as I can tell based on the documentation, one of these should have worked:

The response is evaluated as JSON and must be true for valid elements, and can be any false, undefined or null for invalid elements, using the default message;

Note, the answer to this question may be related to this issue.

Here is the revised code:

$registration.find(".username").each(function() {
    var $this = $(this);
    remote: {
        url:  "does_user_exist.php",
        type: "post",
        data: {entityExistence: function(){return $this.val();} },
        success: function(data){ console.log(data); }
    },
    messages: {
        remote: "Sorry, that username is not available."
   }
});

The PHP script is always returning true or false correctly. According to the documentation, anything except for true should trigger the error message. But the error message doesn't come up. I know error messaging is working because there are other checks are working fine (e.g. rangelength, removed from pasted-in code here for clarity).

Upvotes: 6

Views: 16785

Answers (5)

CIRCLE
CIRCLE

Reputation: 4879

If you need the endpoint to return the validation result as JSON instead of a boolean string like "true" or "false", you can use dataFilter to validate the response.

Let's say you have an endpoint to validate if username exists, that returns the result as:

{"result": true}

You can check the result like this:

$('form').validate({
    rules: {
        username: {
            minlength: 3,
            maxlength: 30,
            remote: {
                url: "/validate/username/",
                type: "post",
                dataType: "json",
                data: {
                    username: function () {
                        return $("#id_username").val()
                    }
                },
                dataFilter: function (response) {
                    response = $.parseJSON(response);
                    return response.result
                }
            }
        },
        ...
});

Upvotes: 0

Sparky
Sparky

Reputation: 98728

The documentation for the remote method states:

The serverside response must be a JSON string that must be "true" for valid elements, and can be "false", undefined, or null for invalid elements, using the default error message. If the serverside response is a string, eg. "That name is already taken, try peter123 instead", this string will be displayed as a custom error message in place of the default.


Quote OP:

"The script does_user_exist.php returns 1 if the user exists."

This might be the opposite of what you want. Since 1 may be getting interpreted as true, which tells the plugin it "passed" validation. As per docs, if the user exists and you want to trigger an error message, the response must be false, undefined, null, or a string (the message).

Upvotes: 3

André Figueira
André Figueira

Reputation: 6696

Unfortunatley the answers above are slightly cryptic.

In order to get it working you need the follow JS.

$('#register-form').validate({
    rules: {
        'first-name': "required",
        'surname': "required",
        'email': {
            required: true,
            email: true,
            remote: {
                url: 'ajax/users/emailInUse',
                type: 'post',
                data: {
                    email: function() {
                        return $('input[name=email]').val();
                    }
                }
            }
        },
        'username': "required",
        'password': "required",
        'confirm-password': {
            equalTo: "input[name=password]"
        }
    },
    messages: {
        'first-name': "Please enter your first name",
        'surname': "Please enter your surname",
        'email': {
            required: "Please enter your email address",
            email: "Please enter a valid email e.g. [email protected]"
        },
        'username': "Please enter a username",
        'password': "Please enter a password",
        'confirm-password': "Passwords do not match"
    }
});

And your backend code should be running the check if the email is valid or not, and return the result as a message within a json string. e.g.

[
    " is already in use..."
]

Example backend code:

public function emailInUseAction()
{

    $this->setJsonResponse();

    if($this->request->isAjax())
    {

        $email = $this->request->getPost('email');

        $emailInUse = Users::emailInUse($email);

        $message = false;

        if($emailInUse)
        {

            $message = $email . ' is already in use...';

        }

        return array(
            $message
        );

    }

}

Hope this helps anyone who encounters the issue!

Upvotes: 2

brentonstrine
brentonstrine

Reputation: 22742

Ok, finally figured it out, randomly. The success callback was apparently ruining everything. All I had to do was remove this:

success: function(data){
    console.log(data);
}

As soon as I did that, everything worked perfectly as expected using simple string responses:

"true"

and

"false"

I can not explain this, but I hope that someone updates the documentation! I noticed that using complete does not break it the way that success does.

Upvotes: 9

Neil Girardi
Neil Girardi

Reputation: 4923

Returning the string does not automatically display it. If you want to display it you need to do something like this:

$('#myDiv').html('<p class="error">Sorry, that user already exists.</p>');

Upvotes: -2

Related Questions