How to Show Error Messages Next to Field
Asked Answered
L

5

31

I have a form with input fields/labels etc. How do I get the error message to show up next to the field? instead of clumped together at the top?

I am using devise, rails 3

I have this at the top of my form:

 = form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
- if resource.errors.any?
  #errorExplanation
    %h2
      = pluralize(resource.errors.count, "error")
      prevented this user from being saved:
    %ul
      - resource.errors.full_messages.each do |msg|
        %li
          = msg
Langrage answered 13/4, 2011 at 9:9 Comment(1)
Good question but I don't think the answer is elegant for UJS formsKrystlekrystyna
E
41

You can use this

- if @resource.errors[:field_name]
  ...

Also useful link:

http://guides.rubyonrails.org/active_record_validations.html#working-with-validation-errors

Englert answered 13/4, 2011 at 9:24 Comment(7)
nice!that looks great! to get the message would i say @resource.errors[:field_name].ful_messages ?Langrage
thanks, is that going to give me a list of errors on one line? i'm trying to do the ffg: for each field, if there are errors on that field, create a div for each error and output it beneath the field, or create 1 div which has a list of errors, 1 below the otherLangrage
Line 1 must have Attribute can't be blank Line 2 must have Attribute can't be shorter than 5 characters etcLangrage
yes, it will return one line error. You can check presence of error just by asking @resource.errors[:field_name].present?Englert
not really what i need, i need multiple lines - i have this - if resource.errors[:firstname].any? - resource.errors[:firstname].each do |msg| %div.error First name = msg ...this works fine but i want to put it into a helper so that i dont repeat it per field...Langrage
@Green guides.rubyonrails.org/…Englert
or @resource.errors[:field_name].any?. present? works because Rails considers an empty array to be blank?.Rhapsodist
C
7

Just create a file in your initializers folder.

config/initializers/inline_errors.rb

Place this code in it:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  unless html_tag =~ /^<label/
    %{<div class="has-error">#{html_tag}<span class="help-block">#{instance.error_message.first}</span></div>}.html_safe
  else
    %{#{html_tag}}.html_safe
  end
end

PD: Sorry for my english.

Cranage answered 18/5, 2016 at 2:26 Comment(4)
No real description provided to guide readers to an answer. This looks super useful though.Bekelja
I placed some text to give some information, my english is bad, therefore I didn't write some text before :/Cranage
Thanks @el_quick. Do you perhaps have an example of how you used this in your form? I am struggling to figure out just exactly how you implemented this. I changed my rating btw. :-)Bekelja
I think field_error_proc is not part of the public API of rails, because it is not documented. If private, this is a dangerous solution.Suffragist
H
5

How about this

if you want to put the error message just beneath the text field, you can do like this

.row.spacer20top
  .col-sm-6.form-group
    = f.label :first_name, "*Your First Name:"
    = f.text_field :first_name, :required => true, class: "form-control"
    = f.error_message_for(:first_name)

What is error_message_for?
--> Well, this is a beautiful hack to do some cool stuff

# Author Shiva Bhusal
# Aug 2016
# in config/initializers/modify_rails_form_builder.rb
# This will add a new method in the `f` object available in Rails forms
class ActionView::Helpers::FormBuilder
  def error_message_for(field_name)
    if self.object.errors[field_name].present?
      model_name              = self.object.class.name.downcase
      id_of_element           = "error_#{model_name}_#{field_name}"
      target_elem_id          = "#{model_name}_#{field_name}"
      class_name              = 'signup-error alert alert-danger'
      error_declaration_class = 'has-signup-error'

      "<div id=\"#{id_of_element}\" for=\"#{target_elem_id}\" class=\"#{class_name}\">"\
      "#{self.object.errors[field_name].join(', ')}"\
      "</div>"\
      "<!-- Later JavaScript to add class to the parent element -->"\
      "<script>"\
          "document.onreadystatechange = function(){"\
            "$('##{id_of_element}').parent()"\
            ".addClass('#{error_declaration_class}');"\
          "}"\
      "</script>".html_safe
    end
  rescue
    nil
  end
end

Result enter image description here

Markup Generated after error

<div id="error_user_first_name" for="user_first_name" class="signup-error alert alert-danger">This field is required.</div>
<script>document.onreadystatechange = function(){$('#error_user_first_name').parent().addClass('has-signup-error');}</script>

Corresponding SCSS

  .has-signup-error{
    .signup-error{
      background: transparent;
      color: $brand-danger;
      border: none;
    }

    input, select{
      background-color: $bg-danger;
      border-color: $brand-danger;
      color: $gray-base;
      font-weight: 500;
    }

    &.checkbox{
      label{
        &:before{
          background-color: $bg-danger;
          border-color: $brand-danger;
        }
      }
    }

Note: Bootstrap variables used here and, do not forget to Restart the server now and after any modification to the file in config dir.

Houston answered 12/8, 2016 at 17:16 Comment(1)
Do you have a solution that doesn't use html_safe ?Burk
K
0

You can use error_message_on http://apidock.com/rails/ActionView/Helpers/ActiveRecordHelper/error_message_on

Update:

form.error_messages was removed from Rails and is now available as a plugin. Please install it with rails plugin install git://github.com/rails/dynamic_form.git.

Kayseri answered 13/4, 2011 at 9:11 Comment(0)
T
0

If anyone is looking for a way how to display error messages for particular field in Rails 6:

a = Post.new
a.save # => false
a.errors.full_messages_for(:title)
["Title can't be blank"]

a.errors.full_messages_for(:title).join(', ')
"Title can't be blank, Title too short"
Tuberculosis answered 12/1, 2021 at 10:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.