Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery validation plugin: valid() does not work with remote validation?

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.

like image 612
hellodally Avatar asked Mar 24 '10 19:03

hellodally


1 Answers

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);
})
like image 71
Charles O. Avatar answered Oct 05 '22 22:10

Charles O.