diff --git a/lib/generators/simple_form/templates/config/initializers/simple_form.rb b/lib/generators/simple_form/templates/config/initializers/simple_form.rb index 2bde7db9..2cb8881d 100644 --- a/lib/generators/simple_form/templates/config/initializers/simple_form.rb +++ b/lib/generators/simple_form/templates/config/initializers/simple_form.rb @@ -14,7 +14,7 @@ SimpleForm.setup do |config| # stack. The options given below are used to wrap the # whole input. config.wrappers :default, class: :input, - hint_class: :field_with_hint, error_class: :field_with_errors do |b| + hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b| ## Extensions enabled by default # Any of these extensions can be disabled for a # given input by passing: `f.input EXTENSION_NAME => false`. diff --git a/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb b/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb index dd27b205..3d09d66c 100644 --- a/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +++ b/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb @@ -12,7 +12,7 @@ SimpleForm.setup do |config| config.button_class = 'btn btn-default' config.boolean_label_class = nil - config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -27,7 +27,7 @@ SimpleForm.setup do |config| b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end - config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -40,7 +40,7 @@ SimpleForm.setup do |config| b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end - config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.optional :readonly @@ -52,7 +52,7 @@ SimpleForm.setup do |config| b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end - config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.optional :readonly b.use :label, class: 'control-label' @@ -61,7 +61,7 @@ SimpleForm.setup do |config| b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end - config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -78,7 +78,7 @@ SimpleForm.setup do |config| end end - config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -93,7 +93,7 @@ SimpleForm.setup do |config| end end - config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.optional :readonly @@ -107,7 +107,7 @@ SimpleForm.setup do |config| end end - config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.optional :readonly @@ -120,7 +120,7 @@ SimpleForm.setup do |config| end end - config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -135,7 +135,7 @@ SimpleForm.setup do |config| b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end - config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b| + config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'no-error' do |b| b.use :html5 b.optional :readonly b.use :label, class: 'control-label' diff --git a/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb b/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb index d4314c73..2515877e 100644 --- a/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +++ b/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb @@ -15,7 +15,7 @@ SimpleForm.setup do |config| # doesn't provide styles for hints. You will need to provide your own CSS styles for hints. # Uncomment them to enable hints. - config.wrappers :vertical_form, class: :input, hint_class: :field_with_hint, error_class: :error do |b| + config.wrappers :vertical_form, class: :input, hint_class: :field_with_hint, error_class: :error, valid_class: :valid do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -29,7 +29,7 @@ SimpleForm.setup do |config| # b.use :hint, wrap_with: { tag: :span, class: :hint } end - config.wrappers :horizontal_form, tag: 'div', class: 'row', hint_class: :field_with_hint, error_class: :error do |b| + config.wrappers :horizontal_form, tag: 'div', class: 'row', hint_class: :field_with_hint, error_class: :error, valid_class: :valid do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -71,7 +71,7 @@ SimpleForm.setup do |config| # Note that you need to adapt this wrapper to your needs. If you need a 4 # columns form then change the wrapper class to 'small-3', if you need # only two use 'small-6' and so on. - config.wrappers :inline_form, tag: 'div', class: 'column small-4', hint_class: :field_with_hint, error_class: :error do |b| + config.wrappers :inline_form, tag: 'div', class: 'column small-4', hint_class: :field_with_hint, error_class: :error, valid_class: :valid do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -90,7 +90,7 @@ SimpleForm.setup do |config| # Examples of use: # - wrapper_html: {class: 'row'}, custom_wrapper_html: {class: 'column small-12'} # - custom_wrapper_html: {class: 'column small-3 end'} - config.wrappers :customizable_wrapper, tag: 'div', error_class: :error do |b| + config.wrappers :customizable_wrapper, tag: 'div', error_class: :error, valid_class: :valid do |b| b.use :html5 b.optional :readonly diff --git a/lib/simple_form.rb b/lib/simple_form.rb index 385d6df9..6d00bb07 100644 --- a/lib/simple_form.rb +++ b/lib/simple_form.rb @@ -229,7 +229,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information. SimpleForm::Wrappers::Root.new(builder.to_a, options) end - wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b| + wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b| b.use :html5 b.use :min_max diff --git a/lib/simple_form/components/errors.rb b/lib/simple_form/components/errors.rb index 2fd02725..b6ea6523 100644 --- a/lib/simple_form/components/errors.rb +++ b/lib/simple_form/components/errors.rb @@ -14,6 +14,16 @@ module SimpleForm object && object.respond_to?(:errors) && errors.present? end + def has_value? + return unless object && object.respond_to?(attribute_name) + + object.send(attribute_name).present? + end + + def valid? + !has_errors? && has_value? + end + protected def error_text diff --git a/lib/simple_form/wrappers/root.rb b/lib/simple_form/wrappers/root.rb index 3a0e0cc4..f70cb00b 100644 --- a/lib/simple_form/wrappers/root.rb +++ b/lib/simple_form/wrappers/root.rb @@ -30,6 +30,7 @@ module SimpleForm end css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors? css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint? + css << (options[:wrapper_valid_class] || @defaults[:valid_class]) if input.valid? css.compact end end diff --git a/test/form_builder/general_test.rb b/test/form_builder/general_test.rb index a4367e8a..9aca83bd 100644 --- a/test/form_builder/general_test.rb +++ b/test/form_builder/general_test.rb @@ -242,6 +242,7 @@ class FormBuilderTest < ActionView::TestCase test 'builder generates file for file columns' do @user.avatar = MiniTest::Mock.new @user.avatar.expect(:public_filename, true) + @user.avatar.expect(:!, false) with_form_for @user, :avatar assert_select 'form input#user_avatar.file' @@ -250,6 +251,7 @@ class FormBuilderTest < ActionView::TestCase test 'builder generates file for attributes that are real db columns but have file methods' do @user.home_picture = MiniTest::Mock.new @user.home_picture.expect(:mounted_as, true) + @user.home_picture.expect(:!, false) with_form_for @user, :home_picture assert_select 'form input#user_home_picture.file'