15

I'm creating a simple demo app that allows a user to enter their email address to register their interest in receiving beta access. The app then sends them a confirmation email that lets them know we've received their request. If you've ever signed up to be notified of a beta launch then you get the idea.

I'm curious about how to handle errors in Rails 3 while using AJAX. Before implementing my respond_to block I had a form that rendered a shared errors partial.

Here's the form.

<% if flash[:notice] %>
<p><%= flash[:notice] %></p>
<% end %>

<p>Sign up to be notified when the beta launches.</p>

<%= form_for @user, :remote => true do |form| %>

    <%= render '/shared/errors', :target => @user %>

    <%= form.label :email, "Your Email Address" %>
    <%= form.text_field :email %>

    <%= form.submit "Notify Me" %>
<% end %>

And here's the aforementioned errors partial.

<% if target.errors.any? %>

<ul>
    <% target.errors.full_messages.each do |message| %>
        <li><%= message %></li>
    <% end %>
</ul>

<% end %>

Very standard stuff. The controller action looks like this.

def create
@user = User.new(params[:user])

respond_to do |format|
  if @user.save
    format.html { redirect_to :back, flash[:notice] = "Thanks for your interest! We'll let you know when the app is in beta." }
    format.js
  else
    format.html { render :action => :new }
    format.js
  end
end
end

Everything works perfectly before implementing ajax. If the form passes validation then they see the success flash message and if not then they see a list of errors. So now that i have a create.js.erb file how should I handle the errors without repeating myself or is that impossible. I obviously want to keep this as DRY as possible.

kyle
  • 151
  • 1
  • 1
  • 3

3 Answers3

16

You can still render a shared partial for all .js errors in your js.erb file.

<% if @user.errors.any? %>
   var el = $('#create_user_form');
   // Create a list of errors
   <%= render :partial=>'js_errors', :locals=>{:target=> @user} %>
 <% else %>
     $('#users_list').append("<%= escape_javascript(render :partial=>"users/show", :locals=>{:user => @user }) %>");
    // Clear form
    el.find('input:text,textarea').val('');
    el.find('.validation-errors').empty();
<% end %>

And your partial could look like (Assuming jquery):

  <% target.errors.full_messages.each do |error| %>
    var errors = $('<ul />');
    errors.append('<li><%= escape_javascript( error ) %></li>');
  <% end %>

But there's also ANOTHER option...It's even DRYer.

http://www.alfajango.com/blog/rails-3-remote-links-and-forms/

If you are working your way through ajax in rails 3, this guide is really the best for understanding responses and ajax rendering as it currently stands.

I worked through this guide and posted in the comments how you can actually use your HTML partials for both HTML and AJAX request responses. I did it by accident and then followed up on how to do it.

Enjoy!

You can actually return straight-up html with your response just like before.

Here's the short version:

def create
     @something = Somethng.new(params[:something])
     if @something.save
       respond_with( @something, :status => :created, :location => @something ) do |format|
         format.html do
           if request.xhr?
             render :partial => "something/show", :locals => { :billable => @billable }, :layout => false
           end
         end
       end
       else
        respond_with( @something.errors, :status => :unprocessable_entity ) do |format|
          format.html do
            if request.xhr?
              render :partial => "something/new", :locals => { :something => @something }, :layout => false
            else
              render :action => :new
            end
          end
        end
      end
    end
Techism
  • 534
  • 3
  • 11
2

I have been facing the same problem a few days ago. I used remote => true option in my form to use Ajax in my Rails 3 application. After that, I have been looking for solution for validating my form fields. After trying a good number of jQuery / Javascript approaches (none of them worked for me though) I came to know about a superb gem called client_side_validations. It is very easy to install by following the instructions on github link (https://github.com/bcardarella/client_side_validations). It works like charm for client side validation of form fields, an awesome gem indeed. Hope this helps with people who are tired of looking for a simple solution for client side validation of model fields after using Ajax in Rails 3 application.

K M Rakibul Islam
  • 33,760
  • 12
  • 89
  • 110
2

I'm not sure the rails remote form way to do it, but my standard mode of operation is to return objects on ajax request in this format:

{ success: true|false,
  data: "html or some other data",
  errors: {} } // jsonified ActiveModel::Errors object

It works very well and lets you render partials into the data field for use on the page, or you can loop through errors in the error object to insert error messages or highlight fields.

Josiah Kiehl
  • 3,593
  • 3
  • 26
  • 28