Saturday, September 10, 2016

An Improved Error Message Bar

When showing error message such as validation errors or any kind of error messages stored in the object instantiated from the class ActiveModel::Errors, the default way to show error messages is ugly and inefficient. Let’s take a look at the validation error handling code generated by rails g scaffold (take model Color for example):
/app/views/colors/_form.html.erb
<%= form_for(color) do |f| %>
  <% if color.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(color.errors.count, "error") %> prohibited this color from being saved:</h2>
      <ul>
        <% color.errors.full_messages.each do |message| %>
          <li><%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %>
    <%= f.text_field :name %>
  </div>

  <div class="action">
    <%= f.submit %>
    <%= link_to 'Back' %>
  </div>
<% end %>
The error message handling code is as follows:
<% if color.errors.any? %>
  <div id="error_explanation">
  <h2><%= pluralize(color.errors.count, "error") %> prohibited this color from being saved:</h2>
    <ul>
      <% color.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div><% end %>
The new.html.erb and edit.html.erb forms call partial form _form.html.erb. However, there are many models using the same code as above except the model name. It is obvious that code refactoring jobs must be done to the error message code.
Besides, the original error message code generates a not very nice-looking web page. It is just few lines of messages shown on top of the page. Why don’t we use the same idea of notice message bar to make a better looking error message bar?

Sure we can, so here is the code and how to implement it:

1. Create a helper method error_message_for(object_habdled)in application_helper.rb.

/app/helpers/applicaiton_helper.rb
def error_message_for(object_handled)
    if object_handled.errors.any?
      close_button_options = { class: "close", "data-dismiss" => "alert", "aria-hidden" => true }
      close_button = content_tag(:button, "×", close_button_options)

      error_content = close_button + error_content
      object_handled.errors.full_messages.each do |message|
        error_content = error_content + message + simple_format("\n")
      end
      content_tag(:div, error_content, id: "error_explanation", class: "alert alert-danger alert-dismissable")
    end
  end

2. Call the helper method in every _form.html.erband assign the model name accordingly.

Insert <%= error_message_for(color) %>on top of the partial form.
For example:
/app/views/color/_form.html.erb
<%= error_message_for(color) %>
<%= form_for(color) do |f| %>
  <div class="field">
    <%= f.label :name %>
    <%= f.text_field :name %>
  </div>
  <div class="action">
    <%= f.submit %>
    <%= link_to 'Back' %>
  </div>
<% end %>
Now, it shows a very nice looking error message bar on top of the page with Bootstrap style.

No comments:

Post a Comment