4

I got started by following this awesome tutorial, but wanted to do the validation on on keyup and place my errors somewhere else. The remote validation shows its own error message at the appropriate times, making me think I had it working. But if I ask specifically if a field with remote validation is valid, it says no, actually, its not.

In application.js I have this...

    $("#new_user").validate({
    rules: {
        "user[login]": {required: true, minlength: 3, remote: "/live_validations/check_login"},
    },
    messages: {
        "user[login]": {required: " ", minlength: " ", remote: " "},
    }
});

$("#user_login").keyup(function(){
    if($(this).valid()){
        $(this).siblings(".feedback").html("0");
    }else{
        $(this).siblings(".feedback").html("1");
    }
})

And then this in the rails app...

def check_login
    @user = User.find_by_login(params[:user][:login])
    respond_to do |format|
      format.json { render :json => @user ? "false" : "true" }    
    end
  end

I think that my problem might have everything to do with this ticket over at jQuery, and tried to implement that code, but, being new to jQuery, it's all a bit over my head. When I say bit, I mean way way.

Any ideas to fix it, or a new way to look at it, would be a big help.

hellodally
  • 265
  • 1
  • 9
  • http://plugins.jquery.com/node/13144 is the ticket I was referring to. 3 points isn't enough to post 2 links in a post :( – hellodally Mar 24 '10 at 19:02

1 Answers1

7

When you call $(this).valid(), it ends up calling /live_validations/check_login asynchronously. The valid() method comes back right away though, not waiting for check_login to finish, and since it doesn't know what the result is going to be, it just returns false.

Looking at the Validation plugin code, I think you should call the element() method instead, which will return true, false, or undefined -- it will return undefined while the asynchronous call is running, whereas valid() only returns true or false. When you get undefined, you know you still have to wait for the call to your server to come back.

I think you can do something like this (untested, but something to play with). Note that the repeated calls to element() will not launch new Ajax calls; they only do so if the value has changed. So there's no harm there.

function checkResult() {
   var valid = $(formSelector).validate().element('#user_login'); // Will not launch a new request if the value hasn't changed
   if (typeof valid == 'undefined') {
     setTimeout("checkResult()", 100);
   }
   else { // it's done!
     if(valid){
      $(this).siblings(".feedback").html("0");
     }else{
      $(this).siblings(".feedback").html("1");
     }
   }
};
$("#user_login").keyup(function(){
  $(formSelector).validate().element('#user_login'); // launches the remote request
  setTimeout("checkResult()", 100);
})
Charles O.
  • 2,237
  • 3
  • 17
  • 21
  • Shoot. I forgot all about this question. I ended up abandoning jquery-validate in favor of something smaller that I rolled myself. This looks awesome though and like it would have worked. A belated acceptance and thank you! – hellodally Dec 10 '10 at 00:55
  • 1
    +1. I used the method described here in an ASP.NET MVC application where I was having a similar issue with the `valid()` method not waiting for remote validation to complete. I had to make some slight modifications for my app, but the idea worked like a charm. Thanks! – Justin Holzer Jul 26 '11 at 21:52
  • 1
    `element` no longer provides `undefined` while the asynchronous call is running. See http://stackoverflow.com/questions/29734937/using-jquery-validators-valid-or-element-method-with-remote-methods for more info. – user1032531 Apr 20 '15 at 20:32