11
email1: {
                    required: true,
                    blacklist: true,
                    beanEmailValidator: true,
                    minlength: 6,
                    maxlength: 70,
                    remote: {
                        type: "GET",
                        url: llbFieldValJSONURL,
                        data: {
                              fieldData : function() {
                                return $("#enterEmail").val();
                              }                           
                         },
                        dataType:"json",
                        dataFilter: function(data) {
                            var json = jQuery.parseJSON(data);
                            if(json.error == "true") {
                                return "\"" + json.errorMessage + "\"";
                            } else {
                                return success;

                            }

                        }
                    }

                }

This function check the uniqueness of a username and returns an error if not unique. The issue is that the remote method won't make any additional calls after being valid.. I need it to trigger every time a value is entered/changed.

For example, if I enter 3 non-unique usernames, the call is made every time. If I enter a unique username, the call is made correctly and the username comes back as valid. So the field is then valid. Now if I enter another non-unique (invalid) username, the remote method won't trigger again.

Wondering if it's somehow caching the response?

invalid (non-unique) response:

{"error":"true","errorMessage":"<b>The User Name you chose is already in use.</b>  Please enter another name."}

valid (unique) response:

{"error":"false","errorMessage":""}

Edit

Saw this on SO:

https://stackoverflow.com/a/1821667/335514

$("#site").change(function() {
  $("#email").removeData("previousValue");
});

So the plugin seems to be caching the response. Does the plugin have a method to switch off caching, or would adding a cache: false to the ajax call do the same thing?

Edit

Neither of these methods worked. It appears that once a field is marked valid, it won't make the remote call again. Thoughts on how to fix? Would putting the function into it's own addMethod prevent this scenario?

Community
  • 1
  • 1
Jason
  • 7,612
  • 14
  • 77
  • 127
  • Yes, `cache: false` should do the same thing. Have you tried it? – Andrew Whitaker Jul 13 '12 at 23:53
  • @AndrewWhitaker - checking in change now. – Jason Jul 14 '12 at 00:08
  • @AndrewWhitaker nope - `cache: false` not working – Jason Jul 14 '12 at 01:05
  • This sounds like a similar problem I had. Ended up putting a 'cache-buster' at the end of the URL when we wanted to force it out of cache state. (This was for jQuery tabs). Something as simple as appending the time in milliseconds as a param should do it – olore Jul 14 '12 at 23:37
  • @olore - may have to try, but question - it will make the call and return with the invalid value/error - and will make the call again, but when it returns as valid/success it won't make the call again - there's got to be a way to invalidate the field... – Jason Jul 15 '12 at 00:56
  • where do you actually check whether it validated? cache:false works by adding a request variable _= to your request header (POST), or url (GET) – ryuusenshi Jul 15 '12 at 01:31
  • @ryuusenshi - here's my response headers - `Cache-Control no-cache, no-cache,no-store,max-age=0` – Jason Jul 15 '12 at 01:35
  • good, but if I understand correctly that shouldn't be the problem, because you're saying that you validation is **executed** only once and you want it to be executed all the time, right? Shouldn't the problem then lie wherein you call for the validation and how this gets triggered? Sorry, if I'm misunderstanding – ryuusenshi Jul 15 '12 at 01:39
  • @ryuusenshi - the remote method will continue to trigger as long as the field is invalid - as soon as I get a response that indicates the field is valid, the remote validation will never trigger again if the values changes. So I can get the field to do 50 remote calls, as long as the value triggers an error response. A valid response causes it to never make the remote call again. – Jason Jul 15 '12 at 03:52
  • What is `success` returned by `dataFilter`? – Andrew Whitaker Jul 15 '12 at 23:21
  • Have you tried setting remote to just `remote: llbFieldValJSONURL` and see what happens then? – ryuusenshi Jul 15 '12 at 23:21
  • @Jason - not sure if you figured this out yet, but in case you haven't try this first: Trigger your remote call, with a value that will return a valid response. Confirm that the response is received in firebug. Now if you change the field to the same value, it should not fire again. At this point, in firebug, call $("#email").removeData("previousValue"); Then change the field again to the same value, and see if the remote call is firing. Also, in my case, I'm not using json for the responses from the remote call, but just a simple string "true" or "false" – Kevin Jhangiani Jul 27 '12 at 02:34
  • Another useful tip - you should be able to consecutively fire the remote call using firebug by doing the following: $("#email").removeData("previousValue"); followed by validator.element('#email'); where validator is the return value when you instantiate var validator = $('#form').validate({...}); – Kevin Jhangiani Jul 27 '12 at 02:35

2 Answers2

8

UPDATE/SOLUTION:

Looking at the source code of jquery.validate.js, particularly this snippet:

success: function(response) {
    validator.settings.messages[element.name].remote = previous.originalMessage;
    var valid = response === true;

    if ( valid ) {   ...

Since the response is evaluated as JSON, you are expected to call return "true". This is also pointed out in the documentation

"The response is evaluated as JSON and must be true for valid elements"

However, it can be quite confusing when looking at the source code that does an exactly equals test for true, if you neglect the fact that the following is implicitly set dataType: json

end update


Upon investigating some more, I'd say that your 'dataFilter' should not be returning 'success'

Refer to Callback function queues @ http://api.jquery.com/jQuery.ajax/

dataFilter callback is invoked immediately upon successful receipt of response data. It receives the returned data and the value of dataType, and must return the (possibly altered) data to pass on to success.

My guess is that your JS breaks on trying to do return success and thus no further validation requests are sent

BenMorel
  • 34,448
  • 50
  • 182
  • 322
ryuusenshi
  • 1,976
  • 13
  • 15
  • I tried it with `return false`, and that does not solve the issue. – Jason Jul 15 '12 at 23:31
  • how about `return data;` ? http://docs.jquery.com/Plugins/Validation/Methods/remote says that the response is evaluated as JSON – ryuusenshi Jul 15 '12 at 23:33
  • causes generic error - if anything is returned, jquery validation takes it as an error... Additionally, the behavior is correct, until the field as be marked as valid - then the call doesn't happen again. – Jason Jul 15 '12 at 23:39
  • The reason for that is because the response (as returned from dataFilter) is evaluated as JSON. – Andrew Whitaker Jul 15 '12 at 23:50
  • Mind reworking your answer with the `return "true"` bit, why it's expecting a string, and I'll give you the bounty (so the answer can be clear for others). – Jason Jul 16 '12 at 13:14
  • Hey. @Jason. I see you have already awarded the bounty, before I've had the chance to update. Thanks. Is the update satisfactory? – ryuusenshi Jul 18 '12 at 05:16
7

I had the same symptoms, but it was caused by a different problem.

It looks like the jQuery remote validation method will not trigger another ajax call if it believes the field's value hasn't changed. This was problematic for me because I have remote validation that validates on two fields in the form: mobile number (IE 555-123-1234) and country code (IE 1 for US).

If the mobile number does not change but the country code does, we need to re-validate. However, the plugin doesn't make another ajax call if the validation is bound to the mobile number field because its value hasn't changed.

You can see where the plugin does this caching in the remote method:

if ( previous.old === optionDataString ) {
    return previous.valid;
}

The plugin stores the previous value using jQuery's $data method and the "previousValue" key. Therefore, in my case all I had to do was clear this value:

$("#my-phone-number-element").removeData("previousValue");
$("#my-phone-number-element").valid();
ledhed2222
  • 675
  • 6
  • 11
  • 1
    +1 for finding this in the source code. I too was having this caching problem but had no idea how to get around a framework quirk like this. This solution is definitely a hack, but an elegant hack :P – Rabadash8820 Nov 06 '17 at 18:02
  • Awesome. You saved my bacon! – fongfan999 Jan 28 '19 at 10:34