25

I'm using sorcery for authentication along with twitter bootstrap.

I'd like to style my error messages on my signup form in the style of twitter's bootstrap by changing the default rails <div class="field_with_errors"> that gets added to the DOM.

What's the rails convention for doing something like this?

I suppose you could add some javascript that manipulates the DOM to rename <div class="field_with_errors">, but that seems like a hack. It seems like there should be a way to override this in rails, but I can't figure out where to do that.

This is how bootstrap requires you to mark up your error to use its built in form error styles:

<div class="control-group error">
  <label class="control-label" for="inputError">Input with error</label>
  <div class="controls">
    <input type="text" id="inputError">
    <span class="help-inline">Please correct the error</span>
  </div>
</div>
Lee McAlilly
  • 9,084
  • 12
  • 60
  • 94
  • 1
    I think you are looking for this
    http://stackoverflow.com/questions/5267998/rails-3-field-with-errors-wrapper-changes-the-page-appearance-how-to-avoid-t
    – Prem Sep 03 '12 at 18:25
  • @prem: Thanks! Was about to link to that myself. – Ryan Bigg Sep 03 '12 at 18:29

6 Answers6

32

From the link above, if you put the following inside class Application < Rails::Application of config/application.rb

config.action_view.field_error_proc = Proc.new { |html_tag, instance| 
  "<div class=\"field_with_errors control-group error\">#{html_tag}</div>".html_safe
}

Your input tags will have a red marker around them whenever validation fails

Un3qual
  • 1,332
  • 15
  • 27
Bibek Shrestha
  • 32,848
  • 7
  • 31
  • 34
  • 4
    This causes in form-horizontal for the label to make the input jump a line, is there a work around? – Nachshon Schwartz Jun 11 '13 at 15:18
  • I changed the behaviour for a single action by adding something inspired by `ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "
    #{html_tag}
    ".html_safe }` inside a particular action method. [ref](http://stackoverflow.com/a/11157784/664833)
    – user664833 Feb 26 '14 at 03:19
17

Using Rails 6 with Bootstrap 4 you'll need to add the is-invalid class. Without getting too fancy I just did:

ActionView::Base.field_error_proc = proc do |html_tag, instance|
  html_tag.gsub("form-control", "form-control is-invalid").html_safe
end
Dex
  • 12,527
  • 15
  • 69
  • 90
1

For Bootstrap 3.2 you could use sth. like this (add nokogiri gem to your Gemfile):

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  html = %(<div class="field_with_errors">#{html_tag}</div>).html_safe
  # add nokogiri gem to Gemfile

  form_fields = [
    'textarea',
    'input',
    'select'
  ]

  elements = Nokogiri::HTML::DocumentFragment.parse(html_tag).css "label, " + form_fields.join(', ')

  elements.each do |e|
    if e.node_name.eql? 'label'
      html = %(<div class="control-group has-error">#{e}</div>).html_safe
    elsif form_fields.include? e.node_name
      if instance.error_message.kind_of?(Array)
        html = %(<div class="control-group has-error">#{html_tag}<span class="help-block">&nbsp;#{instance.error_message.uniq.join(', ')}</span></div>).html_safe
      else
        html = %(<div class="control-group has-error">#{html_tag}<span class="help-block">&nbsp;#{instance.error_message}</span></div>).html_safe
      end
    end
  end
  html
end

Place this code inside config/initializers/field_error_proc.rb file (create one if not exists)

This is slightly modified code from: Overriding ActionView::Base.field_error_proc in Rails

Community
  • 1
  • 1
jmarceli
  • 19,102
  • 6
  • 69
  • 67
0

Note that if you are using SimpleForm, the accepted answer of using a Proc in application.rb won't work. Instead, you should edit the simple_form initializer. For example using Bootstrap 3.2:

config.wrappers :default, class: :input,
  hint_class: :field_with_hint, error_class: :'has-error' do |b|
  [...]
  b.use :hint,  wrap_with: { tag: :span, class: :'text-warning' }
  b.use :error, wrap_with: { tag: :span, class: :'text-danger' }
end
ronan_mac
  • 428
  • 7
  • 16
0

Twitter Bootstrap 3.3.6 on Rails 5, this goes in an initializer customize_error.rb and works for me:

ActionView::Base.field_error_proc = proc { |html_tag, _instance| "<div class=\"has-error\">#{html_tag}</div>".html_safe }
Fab V.
  • 1,052
  • 12
  • 17
0

I wanted to turn off the errors only for checkboxes, so I did this:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  doc = Nokogiri::HTML::Document.parse(html_tag)
  if doc.xpath("//*[@type='checkbox']").any?
    html_tag
  else
    "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe
  end
end
Tintin81
  • 9,821
  • 20
  • 85
  • 178