Question

I have a page that lets one create records - if the validations aren't satisfied, it redirects to the same page and shows an error message. Here's that snip from the controller:

def create
  @signature = Signature.new(signature_params)
    if @signature.save
      redirect_to "/thanks"
    else
      redirect_to :back, :notice => error_messages(@signature)
    end
end 

The trouble is, this is resulting in a full page refresh - so the error message isn't visible because the input form is placed under the fold of the page. I can place it at the top of the page, of course, but is there a way to show the message without reloading the page? Thanks.

Was it helpful?

Solution

OK, so here's what I've settled on:

1) I'm handling validation on the client side with HTML5 "required" attributes - they were created for this explicit purpose and no other gems or plugins are needed. They are supported in all major browsers. Details in this article.

2) I've moved the error messages to the top of the page to handle the case in which a user either is on an old or mobile browser or has JavaScript disabled. Error messages must work with a complete request-response cycle (even if this means re-loading the page) before they work with anything else - this is the unobtrusive JavaScript approach.

3) For the AJAX version, I'm going to be using remote: => true on the form element as explained in the Rails guides. I might be making this open source once I'm done with the callback part of it, and will post a link here.

OTHER TIPS

Obviously, handling errors with flash is the most uniform & DRY way to show the user what's going on, but if you're willing to think outside the box, you'll be able to use Ajax to accomplish a similar job by just handling the errors yourself:


Code Example

#app/controllers/signatures_controller.rb
def create
  @signature = Signature.new(signature_params)
    if @signature.save
      @success = "true"
    end

    respond_to do |format|
        format.js   { @errors = error_messages(@signature) }
        format.html {
            if @success.defined?
                redirect_to "/thanks"
            else
                redirect_to :back, :notice => error_messages(@signature)
            end
        }
    end
end 

#app/views/signatures/create.js.erb
<% unless @success.defined? %>
    alert(<%=j @errors.inspect() %>)
<% end %>

#app/assets/javascripts/signatures.js
$(document).on("submit", "#signature_form", function() {
   $.ajax({
        url: "/signatures"
        type: "POST"
        data: $(this).parent().serialize(); //serialize the form (not the button)
        error: function() {
            alert("Sorry, there was an error!");
        }
   });
});

You'd actually be better using JSON for this. If you like the idea, I can refactor it to include JSON for you!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top