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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With