I have never found a easy way to handle errors in rails with ajax form. Here is my implementation.

You have nothing to change in your view and in your controller, just few line of Javascript.

Here is how it works:

The form

Let’s imagine we have a contact form 3 required fields, name, email and message like this
   1  
   2  <%- form_remote_for @contact, :html => {:class => :contact, :id => :contact_form} do |f| -%>
   3    <label for="name">Name *</label>
   4    <%= f.text_field :name, :class => :text %>
   5    <br/>
   6    
   7    <label for="email">Email *</label>
   8    <%= f.text_field :email, :class => :text %>
   9    <br/>
  10  
  11    <label for="message">Message *</label>
  12    <%= f.text_area :message , :class => :text%>
  13    <br/>   
  14  
  15    <label for="submit">&nbsp;</label>
  16    <%= submit_tag "Submit" %>
  17    <br/>        
  18  <%- end -%>      

We use form_remote_for for ajax post and we set an id to the form for later use. It should look like this

The model

Contact model just have some validations
   1  
   2  class Contact < ActiveRecord::Base
   3    validates_presence_of :name, :email, :message
   4  end

The controller

The controller is a classic REST action create. In this example I just handle Ajax post but you can add code for HTML or XML request. The only thing we need to do is to return an JSON response.
   1  
   2    def create
   3      @contact = Contact.new(params[:contact])
   4      respond_to do |format|
   5        format.js {
   6          if @contact.save
   7            render :json => {:object => "contact", :success => true}
   8          else    
   9            render :json => {:object => "contact", :success => false, :errors => @contact.errors}
  10          end    
  11        }
  12      end
  13    end

Javascript

So how our code will handle this JSON response. The view is a classic remote_form, the model just have validation and our controller returns a JSON string. It’s pretty easy.

With Prototype, you can register function on Ajax callback, here comes the magic:
   1  
   2  Ajax.Responders.register({
   3    onComplete: function(responder, request){  
   4      var response = (request.responseText.evalJSON(true)); 
   5      if (response.object)  {
   6        // Remove old erroes
   7        $(response.object + "_form").select(".error").invoke("removeClassName", "error");
   8        $(response.object + "_form").select(".error_message").invoke("remove");
   9  
  10        // Success: clear all input with text
  11        if (response.success) {
  12          var form = $(response.object + "_form");
  13          form.select(".text").each(function(element) {element.value = ""});
  14        }
  15        // Else add error by creating a div with error message
  16        else {
  17          response.errors.each(function(error) {     
  18            var element = $(response.object + "_" + error[0]);
  19            if (element) {
  20              element.addClassName("error");
  21              element.insert({after: new Element("div", {className: "error_message"}).update(error[1])});
  22            }
  23          })
  24        }
  25      }
  26    }
  27  });       
The result will be like this:

Explanation

If fact everything is JSON data, it contains object name, and errors.

The JS just create divs after any field with error with error message and add an error class to the input. You just need to set some CSS attributes.

3 Responses to “Easy error display on rails ajax form”

  1. Franck Says:

    salut,

    je poste dans ton dernier sujet, car j’ai peut etre plus de chance d’être vu ds les tonnes de commentaires que tu recois :p Tt d’abord super la class Portal. Vraiment extra. Et comme tu l’auras compris c’est mon sujet.

    J’ai un bug de height lors du premier affichage de la page. Certains de mes widgets ne se mettent pas à la taille du contenu. Si je les bouge 1 coup, ils sont ok.

    Verrais tu le pb? j’ai encore un peu de mal avec proto et js.. :’(

    merci d’avance.

  2. Marco Says:

    Where does the “Ajax.Responders.register ” go? in the model?

    thanks!

  3. seb Says:

    @Marco it goes in a JS file (could be application.js)

Sorry, comments are closed for this article.