A blog about TripTie, travel adventures, entrepreneurs, usability, and design.

by Svante Adermark on April 5th, 2006 at 12:34 pm

We validate most of the forms in the TripTie application by using javascript before the form data is actually submitted to the application by using the onsubmit attribute.

When using the javascript helper form_remote_tag for the forms, I first didn’t know where to put the validation since it generates a form html tag with the Ajax call in the onsubmit attribute. One solution is of course to use the :failure callback in the helper tag, but that gets called only if the HTTP-request fails (returns a status code outside the 2XX range) after the action is called and what I wanted to do was to validate before the action was even submitted.

The solution I came up with was, simply, to put the call to the validating javascript functions in the :before callback. The only thing you have to remember to do is return false when the fields don’t validate and not return anything at all when they do. If you return true, the form will submit as a regular form and the Ajax magic will be gone.

This post is categorized in: Code, Ajax, RoR

13 Comments

  1. Rails AJAX pre-submit form validation « Jeff’s Ramblings says:

    […] So a brief little problem I’ve been working on today is how to do some pre-submit client side validation on a form element in rails if I’m using the remote_form_tag to create my tag.  I found a great little solution that was sitting right in front of me the whole time, but it took this article for me to see it.  Basically you just use the :before parameter to call your validation script and then just return false if it fails, how great is that.  Just another rails solution that ends up being easy as long as you just look at the available tools the right way. […]

  2. Buffalo says:

    I have been banging my head against this solution all morning, I just cant seem to get it to work.

    The following combination of the form_remote_tag, :before, and javascript causes the form to still submit and the action to execute.

    Mind to have a look and tell me if I am missing something obvious? I am new to ruby on rails , but relatively adept at javascript, I am hoping I am just doing something blatently wrong .. Thanks! Feel free to email me or I can check back here.

    # the form tag
    “ValidateForm()”,
    :url => { :action => “execute” },

    ) %>

    # the javascript
    function ValidateForm() {

    return false
    }

  3. Svante says:

    This works for me when testing:

    #the controller

    def update
    render :update do |page|
    page.replace_html(”target”, params[:data])
    end
    end

    #the template

    <html>
    <head>
    <style>
    * {
    font-family: Verdana, sans-serif;
    }
    </style>
    </head>
    <body>

    <p>
    Anything you submit in the form should be updated unless you type in “sausage”.
    </p>

    <div id=”target” >
    Nothing again
    </div>

    <%= form_remote_tag :url => {:action => ‘update’},
    :before => “if ($(’data’).value == ’sausage’) {return false}” %>

    <%= text_field_tag ‘data’ %>
    <%= end_form_tag %>

    </body>
    </html>

  4. Alex says:

    Thank You

  5. Yuriy says:

    Hi!
    I have some problem with ajax form validation :(

    I need, that when i leave text_field ajax validate this field and show some error message if needs, whithout submiting.

    Can you help me?
    Thanks!

  6. Amjith PS says:

    Hi,
    But :before tag validation is not working.. ie, when :before returns a false value still it is going with ajax call.

    {:action => ‘update’},
    :before => “if ($(’data’).value == ’sausage’) {return false}” %>

    i like to know whether this is working with you all? i am not getting in right way for form validation :-(

    Thanks a lot
    Cheers
    Amjith PS

  7. Venkat says:

    Hi all, by reading the above comments, I thought that you all might have successfully implemented javascript validation before submitting form to a remote action. But when I tried this with my app, I was left unsuccessful.
    Below is the code I have.
    [code]
    {:action => “does”}, :before => “validate_form()”, :update => “update_div” ) %>

    div updated here
    [/code]

    In my does.rhtml, I am just displaying some text.

    this is my javascript code.
    [code]
    function validate_form()
    {
    var name = document.getElementById(’name’).value;
    var errors = “”;
    if(name != “kishore”)
    {
    errors+= “invalid name”;
    }
    if(errors != “”)
    {
    alert(errors);
    return false;
    }
    }
    [/code]
    When I enter the correct data, the text is getting rendered successfuly but when data is entered incorrectly, the alert message gets displayed and the request is still getting processed and the div is getting updated with the text. Where am I missing the obvious thing? Any help appreciated. thanks in advance.
    Can mail the stuff if the code here is obscure.

    regards,
    venkat

  8. Svante says:

    Using before still works for me, modified the code above to return true in the end of the script and added the if (! validate_form()) {return false;} in the before clause. Tested in ie6, safari and firefox.

  9. Venkat says:

    thanks for the help dude ..but one question
    what does this return
    if (! validate_form()) {return false;}
    when validate_form() is true

  10. Svante says:

    It does not return anything. Before is not supposed to return if everything is normal.

  11. Ezine Readers says:

    Hi,

    I tried the above thing and it successfully run in my application.

    Thanks for posting this help.

    Well one more question regarding this is it possible to do module base validation with ajax like
    in my module if i write validates_presence_of :name and i am submitting the form with form_remote_tag with ajax can it validate with the above mentioned validation.

  12. faz says:

    Should be using this:

    function validate_form() {
    return false;
    }

    {:action => :process_action},
    :update => ‘message’,
    :condition => “validate_form()” ) do %>

  13. Steve says:

    Argh, I wish I had read all of the comments. This post should be updated.

    1) The simplest solution is to use :condition as faz states.

    2) The “problem” everyone is having with the above solution is that it *seems* like you should be able to do:

    :before => “validate()”

    but this isn’t the case. The “before” code is simply anything you want to execute “before” the actual AJAX call. This may be many different statements:

    :before =>”validate();parse();munge()”

    The above “kludge” is to stop the execution of these statements by returning false:

    :before => “if(!validate()) { return false;};parse();munge”

    If validate() returns false, !false is true and the block returns false, halting execution. If validate() returns true, !true is false and the block is false, the return is never executed, and parse() and munge() are executed in turn followed by the AJAX code.

    I add this note because although :condition is clearly better than :before for this use case, there may be other use cases where you do want the execution of statements to stop and then you’ll need to use the if(){ return false;} construction.

    Cheers.

Leave a Comment