Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add an "error" class to the input on error using simple_form?

I need to add a class to the input/textarea/etc when the form is rendered and that field has an error.

<input type="text" class="custom-error-class" />

Is there an easy way to append to SimpleForm's list of CSS classes, but only when the field's corresponding object is an error?

like image 817
Eric M. Avatar asked Feb 04 '14 17:02

Eric M.


5 Answers

I was having the same problem. My solution for this:

I created a new class StringInput (which overrides the original one) and copied the implementation out of the rdoc. I patched that code to check if there are errors on the field itself, if so I add a class invalid.

Because I wanted to use the wrapper options I added a error_class attribute into my initializer.

The full code:

app/inputs/string_input.rb

class StringInput < SimpleForm::Inputs::StringInput
  def input(wrapper_options = nil)
    unless string?
      input_html_classes.unshift("string")
      input_html_options[:type] ||= input_type if html5?
    end

    input_html_classes << wrapper_options[:error_class] if has_errors?
    merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)

    @builder.text_field(attribute_name, merged_input_options)
  end
end

config/initializers/simple_form.rb

SimpleForm.setup do |config|
  config.error_notification_class = 'alert alert-danger'
  config.button_class = 'waves-effect waves-light btn'

  config.wrappers tag: :div, class: :input, error_class: :"error-field" do |b|
    # Form extensions
    b.use :html5
    b.optional :pattern
    b.use :maxlength
    b.use :placeholder
    b.use :readonly

    # Form components
    b.use :label
    b.use :input, class: 'validate', error_class: 'invalid'
    b.use :hint,  wrap_with: { tag: :span, class: :hint }
    b.use :error, wrap_with: { tag: :span, class: :error }
  end
end

This adds a defined error class onto all of your string inputs.

like image 99
Vince V. Avatar answered Nov 18 '22 20:11

Vince V.


simple_form adds field_with_errors class to the wrapper element. You can use this to make your input look different:

.field_with_errors input { ... }
like image 3
Sebastian Avatar answered Nov 18 '22 21:11

Sebastian


It is easier now with simple_form 3.5.0.

Redefine existing input (i.e. StringInput) by creating a new class with the same name (docs). Then override input_html_classes method:

# app/inputs/string_input.rb
class StringInput < SimpleForm::Inputs::StringInput
  def input_html_classes
    has_errors? ? super.push('custom-error-class') : super
  end
end
like image 3
Repolês Avatar answered Nov 18 '22 21:11

Repolês


You can do so using error_html option:

<%= f.input :attr, error_html: { class: 'custom-error-class' } %>
like image 1
vee Avatar answered Nov 18 '22 19:11

vee


Thanks @vince-v,

Using your information I came up with this work in progress for applying the error class to all types of inputs, including labels if they're configured with an error_class.

# lib/inputs/base.rb
module SimpleForm
  module Inputs
    class Base
      def merge_wrapper_options(options, wrapper_options)
        working_wrapper_options = wrapper_options.dup

        if working_wrapper_options
          if working_wrapper_options[:error_class] && has_errors?
            working_wrapper_options[:class] =
              [working_wrapper_options[:class]] + \
              [working_wrapper_options[:error_class]]
          end
          working_wrapper_options.delete(:error_class)

          working_wrapper_options.merge(options) do |key, oldval, newval|
            case key.to_s
            when "class"
              Array(oldval) + Array(newval)
            when "data", "aria"
              oldval.merge(newval)
            else
              newval
            end
          end
        else
          options.dup
        end
      end
    end
  end
end

# config/initializers/simple_form.rb
require 'inputs/base.rb
like image 1
Joe Avatar answered Nov 18 '22 19:11

Joe