diff --git a/README.md b/README.md index d485d3eb..8d11b26b 100644 --- a/README.md +++ b/README.md @@ -66,15 +66,17 @@ Run the generator: rails generate simple_form:install ``` -### Bootstrap +### Bootstrap 5 -**Simple Form** can be easily integrated to the [Bootstrap](http://getbootstrap.com/). -To do that you have to use the `bootstrap` option in the install generator, like this: +**Simple Form** can be easily integrated with [Bootstrap 5](http://getbootstrap.com/). +Use the `bootstrap` option in the install generator, like this: ```console rails generate simple_form:install --bootstrap ``` +This will add an initializer that configures **Simple Form** wrappers for +Bootstrap 5's [form controls](https://getbootstrap.com/docs/5.0/forms/overview/). You have to be sure that you added a copy of the [Bootstrap](http://getbootstrap.com/) assets on your application. diff --git a/lib/generators/simple_form/install_generator.rb b/lib/generators/simple_form/install_generator.rb index 34abd12d..bf7ca065 100644 --- a/lib/generators/simple_form/install_generator.rb +++ b/lib/generators/simple_form/install_generator.rb @@ -5,12 +5,12 @@ module SimpleForm desc "Copy SimpleForm default files" source_root File.expand_path('../templates', __FILE__) class_option :template_engine, desc: 'Template engine to be invoked (erb, haml or slim).' - class_option :bootstrap, type: :boolean, desc: 'Add the Bootstrap wrappers to the SimpleForm initializer.' + class_option :bootstrap, type: :boolean, desc: 'Add the Bootstrap 5 wrappers to the SimpleForm initializer.' class_option :foundation, type: :boolean, desc: 'Add the Zurb Foundation 5 wrappers to the SimpleForm initializer.' def info_bootstrap return if options.bootstrap? || options.foundation? - puts "SimpleForm 3 supports Bootstrap and Zurb Foundation 5. If you want "\ + puts "SimpleForm supports Bootstrap 5 and Zurb Foundation 5. If you want "\ "a configuration that is compatible with one of these frameworks, then please " \ "re-run this generator with --bootstrap or --foundation as an option." end 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 0f7a31d7..956d8ec4 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 @@ -49,7 +49,7 @@ SimpleForm.setup do |config| # vertical forms # # vertical default_wrapper - config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_form, class: 'mb-3' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -57,90 +57,100 @@ SimpleForm.setup do |config| b.optional :pattern b.optional :min_max b.optional :readonly - b.use :label + b.use :label, class: 'form-label' b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :full_error, wrap_with: { class: 'invalid-feedback' } + b.use :hint, wrap_with: { class: 'form-text' } end # vertical input for boolean - config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_boolean, tag: 'fieldset', class: 'mb-3' do |b| b.use :html5 b.optional :readonly - b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb| + b.wrapper :form_check_wrapper, class: 'form-check' do |bb| bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' bb.use :label, class: 'form-check-label' - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + bb.use :full_error, wrap_with: { class: 'invalid-feedback' } + bb.use :hint, wrap_with: { class: 'form-text' } end end # vertical input for radio buttons and check boxes - config.wrappers :vertical_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'fieldset', class: 'mb-3' do |b| b.use :html5 b.optional :readonly b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba| ba.use :label_text end b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :full_error, wrap_with: { class: 'invalid-feedback d-block' } + b.use :hint, wrap_with: { class: 'form-text' } end # vertical input for inline radio buttons and check boxes - config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'fieldset', class: 'mb-3' do |b| b.use :html5 b.optional :readonly b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba| ba.use :label_text end b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :full_error, wrap_with: { class: 'invalid-feedback d-block' } + b.use :hint, wrap_with: { class: 'form-text' } end # vertical file input - config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_file, class: 'mb-3' do |b| b.use :html5 b.use :placeholder b.optional :maxlength b.optional :minlength b.optional :readonly - b.use :label - b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :label, class: 'form-label' + b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :full_error, wrap_with: { class: 'invalid-feedback' } + b.use :hint, wrap_with: { class: 'form-text' } + end + + # vertical select input + config.wrappers :vertical_select, class: 'mb-3' do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: 'form-label' + b.use :input, class: 'form-select', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :full_error, wrap_with: { class: 'invalid-feedback' } + b.use :hint, wrap_with: { class: 'form-text' } end # vertical multi select - config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_multi_select, class: 'mb-3' do |b| b.use :html5 b.optional :readonly - b.use :label - b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba| - ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :label, class: 'form-label' + b.wrapper class: 'd-flex flex-row justify-content-between align-items-center' do |ba| + ba.use :input, class: 'form-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid' end - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :full_error, wrap_with: { class: 'invalid-feedback d-block' } + b.use :hint, wrap_with: { class: 'form-text' } end # vertical range input - config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :vertical_range, class: 'mb-3' do |b| b.use :html5 b.use :placeholder b.optional :readonly b.optional :step - b.use :label - b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :label, class: 'form-label' + b.use :input, class: 'form-range', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :full_error, wrap_with: { class: 'invalid-feedback' } + b.use :hint, wrap_with: { class: 'form-text' } end # horizontal forms # # horizontal default_wrapper - config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_form, class: 'row mb-3' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -149,94 +159,103 @@ SimpleForm.setup do |config| b.optional :min_max b.optional :readonly b.use :label, class: 'col-sm-3 col-form-label' - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba| + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + ba.use :full_error, wrap_with: { class: 'invalid-feedback' } + ba.use :hint, wrap_with: { class: 'form-text' } end end # horizontal input for boolean - config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_boolean, class: 'row mb-3' do |b| b.use :html5 b.optional :readonly - b.wrapper tag: 'label', class: 'col-sm-3' do |ba| - ba.use :label_text - end - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr| - wr.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb| + b.wrapper :grid_wrapper, class: 'col-sm-9 offset-sm-3' do |wr| + wr.wrapper :form_check_wrapper, class: 'form-check' do |bb| bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' bb.use :label, class: 'form-check-label' - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + bb.use :full_error, wrap_with: { class: 'invalid-feedback' } + bb.use :hint, wrap_with: { class: 'form-text' } end end end # horizontal input for radio buttons and check boxes - config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', class: 'row mb-3' do |b| b.use :html5 b.optional :readonly b.use :label, class: 'col-sm-3 col-form-label pt-0' - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba| + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + ba.use :full_error, wrap_with: { class: 'invalid-feedback d-block' } + ba.use :hint, wrap_with: { class: 'form-text' } end end # horizontal input for inline radio buttons and check boxes - config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', class: 'row mb-3' do |b| b.use :html5 b.optional :readonly b.use :label, class: 'col-sm-3 col-form-label pt-0' - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba| + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + ba.use :full_error, wrap_with: { class: 'invalid-feedback d-block' } + ba.use :hint, wrap_with: { class: 'form-text' } end end # horizontal file input - config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_file, class: 'row mb-3' do |b| b.use :html5 b.use :placeholder b.optional :maxlength b.optional :minlength b.optional :readonly b.use :label, class: 'col-sm-3 col-form-label' - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba| - ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid' - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| + ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' + ba.use :full_error, wrap_with: { class: 'invalid-feedback' } + ba.use :hint, wrap_with: { class: 'form-text' } + end + end + + # horizontal select input + config.wrappers :horizontal_select, class: 'row mb-3' do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: 'col-sm-3 col-form-label' + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| + ba.use :input, class: 'form-select', error_class: 'is-invalid', valid_class: 'is-valid' + ba.use :full_error, wrap_with: { class: 'invalid-feedback' } + ba.use :hint, wrap_with: { class: 'form-text' } end end # horizontal multi select - config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_multi_select, class: 'row mb-3' do |b| b.use :html5 b.optional :readonly b.use :label, class: 'col-sm-3 col-form-label' - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba| - ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb| - bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid' + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| + ba.wrapper class: 'd-flex flex-row justify-content-between align-items-center' do |bb| + bb.use :input, class: 'form-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid' end - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + ba.use :full_error, wrap_with: { class: 'invalid-feedback d-block' } + ba.use :hint, wrap_with: { class: 'form-text' } end end # horizontal range input - config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :horizontal_range, class: 'row mb-3' do |b| b.use :html5 b.use :placeholder b.optional :readonly b.optional :step - b.use :label, class: 'col-sm-3 col-form-label' - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba| - ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid' - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :label, class: 'col-sm-3 col-form-label pt-0' + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba| + ba.use :input, class: 'form-range', error_class: 'is-invalid', valid_class: 'is-valid' + ba.use :full_error, wrap_with: { class: 'invalid-feedback' } + ba.use :hint, wrap_with: { class: 'form-text' } end end @@ -244,7 +263,7 @@ SimpleForm.setup do |config| # inline forms # # inline default_wrapper - config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :inline_form, class: 'col-12' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -252,140 +271,66 @@ SimpleForm.setup do |config| b.optional :pattern b.optional :min_max b.optional :readonly - b.use :label, class: 'sr-only' + b.use :label, class: 'visually-hidden' b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :error, wrap_with: { class: 'invalid-feedback' } + b.optional :hint, wrap_with: { class: 'form-text' } end # inline input for boolean - config.wrappers :inline_boolean, tag: 'span', class: 'form-check mb-2 mr-sm-2', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :inline_boolean, class: 'col-12' do |b| b.use :html5 b.optional :readonly - b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :label, class: 'form-check-label' - b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.wrapper :form_check_wrapper, class: 'form-check' do |bb| + bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' + bb.use :label, class: 'form-check-label' + bb.use :error, wrap_with: { class: 'invalid-feedback' } + bb.optional :hint, wrap_with: { class: 'form-text' } + end end # bootstrap custom forms # - # custom input for boolean - config.wrappers :custom_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - b.use :html5 - b.optional :readonly - b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb| - bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid' - bb.use :label, class: 'custom-control-label' - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - end - end - # custom input switch for boolean - config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :custom_boolean_switch, class: 'mb-3' do |b| b.use :html5 b.optional :readonly - b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-switch' do |bb| - bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid' - bb.use :label, class: 'custom-control-label' + b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check form-switch' do |bb| + bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid' + bb.use :label, class: 'form-check-label' bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + bb.use :hint, wrap_with: { class: 'form-text' } end end - # custom input for radio buttons and check boxes - config.wrappers :custom_collection, item_wrapper_class: 'custom-control', item_label_class: 'custom-control-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - b.use :html5 - b.optional :readonly - b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba| - ba.use :label_text - end - b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - end - - # custom input for inline radio buttons and check boxes - config.wrappers :custom_collection_inline, item_wrapper_class: 'custom-control custom-control-inline', item_label_class: 'custom-control-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - b.use :html5 - b.optional :readonly - b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba| - ba.use :label_text - end - b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - end - - # custom file input - config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - b.use :html5 - b.use :placeholder - b.optional :maxlength - b.optional :minlength - b.optional :readonly - b.use :label - b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba| - ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid' - ba.use :label, class: 'custom-file-label' - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - end - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - end - - # custom multi select - config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - b.use :html5 - b.optional :readonly - b.use :label - b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba| - ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid' - end - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - end - - # custom range input - config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - b.use :html5 - b.use :placeholder - b.optional :readonly - b.optional :step - b.use :label - b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid' - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - end - # Input Group - custom component # see example app and config at https://github.com/heartcombo/simple_form-bootstrap - # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| - # b.use :html5 - # b.use :placeholder - # b.optional :maxlength - # b.optional :minlength - # b.optional :pattern - # b.optional :min_max - # b.optional :readonly - # b.use :label - # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba| - # ba.optional :prepend - # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' - # ba.optional :append - # end - # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' } - # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } - # end + config.wrappers :input_group, class: 'mb-3' do |b| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :label, class: 'form-label' + b.wrapper :input_group_tag, class: 'input-group' do |ba| + ba.optional :prepend + ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' + ba.optional :append + ba.use :full_error, wrap_with: { class: 'invalid-feedback' } + end + b.use :hint, wrap_with: { class: 'form-text' } + end # Floating Labels form # # floating labels default_wrapper - config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :floating_labels_form, class: 'form-floating mb-3' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -395,18 +340,18 @@ SimpleForm.setup do |config| b.optional :readonly b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' b.use :label - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :full_error, wrap_with: { class: 'invalid-feedback' } + b.use :hint, wrap_with: { class: 'form-text' } end # custom multi select - config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + config.wrappers :floating_labels_select, class: 'form-floating mb-3' do |b| b.use :html5 b.optional :readonly - b.use :input, class: 'custom-select', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :input, class: 'form-select', error_class: 'is-invalid', valid_class: 'is-valid' b.use :label - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + b.use :full_error, wrap_with: { class: 'invalid-feedback' } + b.use :hint, wrap_with: { class: 'form-text' } end @@ -423,18 +368,7 @@ SimpleForm.setup do |config| file: :vertical_file, radio_buttons: :vertical_collection, range: :vertical_range, - time: :vertical_multi_select + time: :vertical_multi_select, + select: :vertical_select } - - # enable custom form wrappers - # config.wrapper_mappings = { - # boolean: :custom_boolean, - # check_boxes: :custom_collection, - # date: :custom_multi_select, - # datetime: :custom_multi_select, - # file: :custom_file, - # radio_buttons: :custom_collection, - # range: :custom_range, - # time: :custom_multi_select - # } end