From 1cb66eb86bc44dfeabe6c7afe955dc59c9773592 Mon Sep 17 00:00:00 2001 From: m5o Date: Wed, 11 Apr 2018 14:47:16 +0200 Subject: [PATCH] update bootstrap v4.1 generator template (#1569) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit simple form now 💜 bootstrap 4.1 The bootstrap generator is extracted from: https://github.com/rafaelfranca/simple_form-bootstrap/pull/56 * supported form wrapper all covered by *tests* * vertical form * horizontal form * inline form * custom fields form * input groups form * floating labels form :link: https://github.com/rafaelfranca/simple_form-bootstrap/pull/56 :link: https://github.com/plataformatec/simple_form/issues/1561 Resolves #1337 --- CHANGELOG.md | 3 +- lib/generators/simple_form/templates/README | 6 +- .../initializers/simple_form_bootstrap.rb | 455 ++++++++++++++---- 3 files changed, 369 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f978288c..61c69e53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## Unreleased +* Add bootstrap v4.1 generator template. [@m5o](https://github.com/m5o) * Add Rails 5.2 support. [@gobijan](https://github.com/gobijan) * Add API to register custom components.[@feliperenan](https://github.com/feliperenan) * Allow custom errors classes to inputs.[@feliperenan](https://github.com/feliperenan) @@ -23,7 +24,7 @@ * Add frozen_string_literal magic comment to several files. [@oniofchaos](https://github.com/oniofchaos) * Try convert @object to model in case we got decorated object [@timurvafin](https://github.com/timurvafin) - From now, if you are using some object that inherits from `SimpleDelegator`, you must implement - `def to_model; self; end`. Otherwise, *Simple Form* will convert the decorated object to the model + `def to_model; self; end`. Otherwise, *Simple Form* will convert the decorated object to the model since `SimpleDelegator` will delegate it to the model. * Code cleanup [@Fornacula](https://github.com/Fornacula) diff --git a/lib/generators/simple_form/templates/README b/lib/generators/simple_form/templates/README index fba4fc6d..1713a991 100644 --- a/lib/generators/simple_form/templates/README +++ b/lib/generators/simple_form/templates/README @@ -3,9 +3,9 @@ Be sure to have a copy of the Bootstrap stylesheet available on your application, you can get it on http://getbootstrap.com/. - Inside your views, use the 'simple_form_for' with one of the Bootstrap form - classes, '.form-horizontal' or '.form-inline', as the following: + Inside your views, use the 'simple_form_for' with the Bootstrap form + class, '.form-inline', as the following: - = simple_form_for(@user, html: { class: 'form-horizontal' }) do |form| + = simple_form_for(@user, html: { class: 'form-inline' }) do |form| =============================================================================== 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 28329323..0178fd53 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 @@ -1,18 +1,55 @@ # frozen_string_literal: true -# + +# Please do not make direct changes to this file! +# This generator is maintained by the community around simple_form-bootstrap: +# https://github.com/rafaelfranca/simple_form-bootstrap +# All future development, tests, and organization should happen there. +# Background history: https://github.com/plataformatec/simple_form/issues/1561 + # Uncomment this and change the path if necessary to include your own # components. -# See https://github.com/plataformatec/simple_form#custom-components to know -# more about custom components. +# See https://github.com/plataformatec/simple_form#custom-components +# to know more about custom components. # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f } -# + # Use this setup block to configure all options available in SimpleForm. SimpleForm.setup do |config| + # Default class for buttons + config.button_class = 'btn' + + # Define the default class of the input wrapper of the boolean input. + config.boolean_label_class = 'form-check-label' + + # How the label text should be generated altogether with the required text. + config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" } + + # Define the way to render check boxes / radio buttons with labels. + config.boolean_style = :inline + + # You can wrap each item in a collection of radio/check boxes with a tag + config.item_wrapper_tag = :div + + # Defines if the default input wrapper class should be included in radio + # collection wrappers. + config.include_default_input_wrapper_class = false + + # CSS class to add for error notification helper. config.error_notification_class = 'alert alert-danger' - config.button_class = 'btn btn-default' - config.boolean_label_class = nil - config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # :to_sentence to list all errors for each field. + config.error_method = :to_sentence + + # add validation classes to `input_field` + config.input_field_error_class = 'is-invalid' + config.input_field_valid_class = 'is-valid' + + + # 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| b.use :html5 b.use :placeholder b.optional :maxlength @@ -20,48 +57,90 @@ SimpleForm.setup do |config| b.optional :pattern b.optional :min_max b.optional :readonly - b.use :label, class: 'control-label' - - b.use :input, class: 'form-control' - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :label, class: 'form-control-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' } end - config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # 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| + b.use :html5 + b.optional :readonly + b.wrapper :form_check_wrapper, tag: 'div', 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' } + end + end + + # vertical input for radio buttons and check boxes + config.wrappers :vertical_collection, item_wrapper_class: 'form-check', 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: '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' } + end + + # vertical input for inline radio buttons and check boxes + config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', 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: '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' } + 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| b.use :html5 b.use :placeholder b.optional :maxlength b.optional :minlength b.optional :readonly - b.use :label, class: 'control-label' - - b.use :input - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + 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 d-block' } + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } end - config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # 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| b.use :html5 b.optional :readonly - - b.wrapper tag: 'div', class: 'checkbox' do |ba| - ba.use :label_input + b.use :label, class: 'form-control-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' end - - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + 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 :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # vertical range input + config.wrappers :vertical_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.use :label, class: 'control-label' - b.use :input - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + 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' } end - config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + + # 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| b.use :html5 b.use :placeholder b.optional :maxlength @@ -69,58 +148,103 @@ SimpleForm.setup do |config| b.optional :pattern b.optional :min_max b.optional :readonly - b.use :label, class: 'col-sm-3 control-label' - - b.wrapper tag: 'div', class: 'col-sm-9' do |ba| - ba.use :input, class: 'form-control' - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + 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', 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' } end end - config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # 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| b.use :html5 - b.use :placeholder - b.optional :maxlength - b.optional :minlength b.optional :readonly - b.use :label, class: 'col-sm-3 control-label' - - b.wrapper tag: 'div', class: 'col-sm-9' do |ba| - ba.use :input - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.wrapper tag: 'label', class: 'col-sm-3' do |ba| + ba.use :label_text end - end - - config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| - b.use :html5 - b.optional :readonly - - b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr| - wr.wrapper tag: 'div', class: 'checkbox' do |ba| - ba.use :label_input + b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr| + wr.wrapper :form_check_wrapper, tag: 'div', 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' } end - - wr.use :error, wrap_with: { tag: 'span', class: 'help-block' } - wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' } end end - config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # horizontal input for radio buttons and check boxes + config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| b.use :html5 b.optional :readonly - - b.use :label, class: 'col-sm-3 control-label' - - b.wrapper tag: 'div', class: 'col-sm-9' do |ba| - ba.use :input - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + b.use :label, class: 'col-sm-3 form-control-label' + b.wrapper :grid_wrapper, tag: 'div', 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' } end end - config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # horizontal input for inline radio buttons and check boxes + config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| + b.use :html5 + b.optional :readonly + b.use :label, class: 'col-sm-3 form-control-label' + b.wrapper :grid_wrapper, tag: 'div', 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' } + 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| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :readonly + b.use :label, class: 'col-sm-3 form-control-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' } + 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| + b.use :html5 + b.optional :readonly + b.use :label, class: 'col-sm-3 control-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' + 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' } + 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| + b.use :html5 + b.use :placeholder + b.optional :readonly + b.optional :step + b.use :label, class: 'col-sm-3 form-control-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' } + end + end + + + # inline forms + # + # inline default_wrapper + config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| b.use :html5 b.use :placeholder b.optional :maxlength @@ -130,37 +254,186 @@ SimpleForm.setup do |config| b.optional :readonly b.use :label, class: 'sr-only' - b.use :input, class: 'form-control' - b.use :error, wrap_with: { tag: 'span', class: 'help-block' } - b.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + 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' } end - config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error', valid_class: 'has-success' do |b| + # inline input for boolean + config.wrappers :inline_boolean, tag: 'span', class: 'form-check flex-wrap justify-content-start mr-sm-2', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b| b.use :html5 b.optional :readonly - b.use :label, class: 'control-label' - b.wrapper tag: 'div', class: 'form-inline' do |ba| - ba.use :input, class: 'form-control' - ba.use :error, wrap_with: { tag: 'span', class: 'help-block' } - ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' } + 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' } + 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 - # Wrappers for forms and inputs using the Bootstrap toolkit. - # Check the Bootstrap docs (http://getbootstrap.com) - # to learn about the different styles for forms and inputs, - # buttons and other elements. + + config.wrappers :custom_boolean_switch, 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-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' + 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 for radio buttons and check boxes + config.wrappers :custom_collection, item_wrapper_class: 'custom-control', 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', 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, class: 'form-control-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, class: 'form-control-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, class: 'form-control-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/rafaelfranca/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, class: 'form-control-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 + + + # 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| + b.use :html5 + b.use :placeholder + b.optional :maxlength + b.optional :minlength + b.optional :pattern + b.optional :min_max + b.optional :readonly + b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :label, class: 'form-control-label' + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + 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| + b.use :html5 + b.optional :readonly + b.use :input, class: 'custom-select custom-select-lg', error_class: 'is-invalid', valid_class: 'is-valid' + b.use :label, class: 'form-control-label' + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' } + b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' } + end + + + # The default wrapper to be used by the FormBuilder. config.default_wrapper = :vertical_form + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. config.wrapper_mappings = { - check_boxes: :vertical_radio_and_checkboxes, - radio_buttons: :vertical_radio_and_checkboxes, - file: :vertical_file_input, - boolean: :vertical_boolean, - datetime: :multi_select, - date: :multi_select, - time: :multi_select + boolean: :vertical_boolean, + check_boxes: :vertical_collection, + date: :vertical_multi_select, + datetime: :vertical_multi_select, + file: :vertical_file, + radio_buttons: :vertical_collection, + range: :vertical_range, + time: :vertical_multi_select } - # Defines validation classes to the input_field. By default it's nil. - # config.input_field_valid_class = 'is-valid' - # config.input_field_error_class = 'is-invalid' + # 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