simple_form 3.5.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 26d8e98f7207ee39c87221a646468a32291c982b
4
- data.tar.gz: c3706e88eef3b4804381d8dbafd343819dbea517
3
+ metadata.gz: bdc43deadddaaf9bc4b3872855d677c5e560066d
4
+ data.tar.gz: 1a58416a2a4977e825f25c345ba41abec78c85a9
5
5
  SHA512:
6
- metadata.gz: ee943633a1817a276e27b2aa55a9767169bf75791e17d0fe236f10c057f9442187ca0f6914da62e070a5418ec06c9d31dd61c2f662ee4c99fe52cec02ec1edd0
7
- data.tar.gz: f5019c5c6b057a008d5c1403d030798f3bdf2393b42410afa1cdc3e8feecd4c79e4a721a3a1fd976f147460ca497a199f9092834d4d26fb32d76c1cadbab2454
6
+ metadata.gz: 9812df086c46e0abe897274ac1260cac8dccb7d906da88f75182efc741a4802931f0c5c8b556dfa1ab0793cf93fe9cd68909d69948cee1f43f26b7a807e3ae29
7
+ data.tar.gz: dca2a8eaf706656f77f5294a18068521aa83a9ab2fbd1e269009e68751e9ea2d2811127d5daa017d137c5c9ec5c74b62bbfaaa3fb002211f6778d09cb19a066c
@@ -1,11 +1,34 @@
1
1
  ## Unreleased
2
2
 
3
+ ## 4.0.0
4
+
5
+ ### Enhancements
6
+ * Add bootstrap v4.1 generator template. [@m5o](https://github.com/m5o)
7
+ * Add Rails 5.2 support. [@gobijan](https://github.com/gobijan)
8
+ * Add API to register custom components.[@feliperenan](https://github.com/feliperenan)
9
+ * Allow custom errors classes to inputs.[@feliperenan](https://github.com/feliperenan)
10
+ * Remove support from Rails 4.0, 4.1 and 4.2. [@feliperenan](https://github.com/feliperenan)
11
+ * Add support for citext, hstore, json & jsonb column types. [@swrobel](https://github.com/swrobel)
12
+ * Add :valid_class on input wrapper when value is present and valid [@aeberlin](https://github.com/aeberlin), [@m5o](https://github.com/m5o)
13
+ * Allow :valid_class to inputs when value is present and valid. [@m5o](https://github.com/m5o)
14
+ * Allow validation classes on input_field. [@feliperenan](https://github.com/feliperenan)
15
+ * Add basic ActiveStorage support. [@murb](https://github.com/murb)
16
+
17
+ ### Bug fix
18
+ * Fix horizontal form label position, from right to text-right. [@cavpollo](https://github.com/cavpollo)
19
+ * Add base error display alongside existing errors. [@bluefalcon26](https://github.com/bluefalcon26)
20
+ * Silent deprication warning for placeholder_text. [@moofkit](https://github.com/moofkit)
21
+ * Use custom i18n scope for label required html. [@tvdeyen](https://github.com/tvdeyen)
22
+
3
23
  ## 3.5.1
4
24
 
5
25
  ### Enhancements
6
26
  * Exclude hidden field when unchecked_value: false. [@fschwahn](https://github.com/fschwahn)
7
27
  * Add frozen_string_literal magic comment to several files. [@oniofchaos](https://github.com/oniofchaos)
8
28
  * Try convert @object to model in case we got decorated object [@timurvafin](https://github.com/timurvafin)
29
+ - From now, if you are using some object that inherits from `SimpleDelegator`, you must implement
30
+ `def to_model; self; end`. Otherwise, *Simple Form* will convert the decorated object to the model
31
+ since `SimpleDelegator` will delegate it to the model.
9
32
  * Code cleanup [@Fornacula](https://github.com/Fornacula)
10
33
 
11
34
  ### Bug fix
data/README.md CHANGED
@@ -555,6 +555,7 @@ Mapping | Generated HTML Element | Database Column Type
555
555
  --------------- |--------------------------------------|---------------------
556
556
  `boolean` | `input[type=checkbox]` | `boolean`
557
557
  `string` | `input[type=text]` | `string`
558
+ `citext` | `input[type=text]` | `citext`
558
559
  `email` | `input[type=email]` | `string` with `name =~ /email/`
559
560
  `url` | `input[type=url]` | `string` with `name =~ /url/`
560
561
  `tel` | `input[type=tel]` | `string` with `name =~ /phone/`
@@ -562,6 +563,9 @@ Mapping | Generated HTML Element | Database Column Type
562
563
  `search` | `input[type=search]` | -
563
564
  `uuid` | `input[type=text]` | `uuid`
564
565
  `text` | `textarea` | `text`
566
+ `hstore` | `textarea` | `hstore`
567
+ `json` | `textarea` | `json`
568
+ `jsonb` | `textarea` | `jsonb`
565
569
  `file` | `input[type=file]` | `string` responding to file methods
566
570
  `hidden` | `input[type=hidden]` | -
567
571
  `integer` | `input[type=number]` | `integer`
@@ -852,7 +856,8 @@ The syntax looks like this:
852
856
 
853
857
  ```ruby
854
858
  config.wrappers tag: :div, class: :input,
855
- error_class: :field_with_errors do |b|
859
+ error_class: :field_with_errors,
860
+ valid_class: :field_without_errors do |b|
856
861
 
857
862
  # Form extensions
858
863
  b.use :html5
@@ -901,11 +906,12 @@ You can customize _Form components_ passing options to them:
901
906
 
902
907
  ```ruby
903
908
  config.wrappers do |b|
904
- b.use :label_input, class: 'label-input-class'
909
+ b.use :label_input, class: 'label-input-class', error_class: 'is-invalid', valid_class: 'is-valid'
905
910
  end
906
911
  ```
907
912
 
908
- This you set the input and label class to `'label-input-class'`.
913
+ This you set the input and label class to `'label-input-class'` and will set the class `'is-invalid'`
914
+ when the input has errors and `'is-valid'` if the input is valid.
909
915
 
910
916
  If you want to customize the custom _Form components_ on demand you can give it a name like this:
911
917
 
@@ -984,6 +990,92 @@ when the content is present.
984
990
  end
985
991
  ```
986
992
 
993
+ ## Custom Components
994
+
995
+ When you use custom wrappers, you might also be looking for a way to add custom components to your
996
+ wrapper. The default components are:
997
+
998
+ ```ruby
999
+ :label # The <label> tag alone
1000
+ :input # The <input> tag alone
1001
+ :label_input # The <label> and the <input> tags
1002
+ :hint # The hint for the input
1003
+ :error # The error for the input
1004
+ ```
1005
+
1006
+ A custom component might be interesting for you if your views look something like this:
1007
+
1008
+ ```erb
1009
+ <%= simple_form_for @blog do |f| %>
1010
+ <div class="row">
1011
+ <div class="span1 number">
1012
+ 1
1013
+ </div>
1014
+ <div class="span8">
1015
+ <%= f.input :title %>
1016
+ </div>
1017
+ </div>
1018
+ <div class="row">
1019
+ <div class="span1 number">
1020
+ 2
1021
+ </div>
1022
+ <div class="span8">
1023
+ <%= f.input :body, as: :text %>
1024
+ </div>
1025
+ </div>
1026
+ <% end %>
1027
+ ```
1028
+
1029
+ A cleaner method to create your views would be:
1030
+
1031
+ ```erb
1032
+ <%= simple_form_for @blog, wrapper: :with_numbers do |f| %>
1033
+ <%= f.input :title, number: 1 %>
1034
+ <%= f.input :body, as: :text, number: 2 %>
1035
+ <% end %>
1036
+ ```
1037
+
1038
+ To use the number option on the input, first, tells to Simple Form the place where the components
1039
+ will be:
1040
+
1041
+ ``` ruby
1042
+ # config/initializers/simple_form.rb
1043
+ Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
1044
+ ```
1045
+
1046
+ Create a new component within the path specified above:
1047
+
1048
+ ```ruby
1049
+ # lib/components/numbers_component.rb
1050
+ module NumbersComponent
1051
+ # To avoid deprecation warning, you need to make the wrapper_options explicit
1052
+ # even when they won't be used.
1053
+ def number(wrapper_options = nil)
1054
+ @number ||= begin
1055
+ options[:number].to_s.html_safe if options[:number].present?
1056
+ end
1057
+ end
1058
+ end
1059
+
1060
+ SimpleForm.include_component(NumbersComponent)
1061
+ ```
1062
+
1063
+ Finally, add a new wrapper to the config/initializers/simple_form.rb file:
1064
+
1065
+ ```ruby
1066
+ config.wrappers :with_numbers, tag: 'div', class: 'row', error_class: 'error' do |b|
1067
+ b.use :html5
1068
+ b.use :number, wrap_with: { tag: 'div', class: 'span1 number'}
1069
+ b.wrapper tag: 'div', class: 'span8' do |ba|
1070
+ ba.use :placeholder
1071
+ ba.use :label
1072
+ ba.use :input
1073
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
1074
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
1075
+ end
1076
+ end
1077
+ ```
1078
+
987
1079
  ## HTML 5 Notice
988
1080
 
989
1081
  By default, **Simple Form** will generate input field types and attributes that are supported in HTML5,
@@ -1049,6 +1141,76 @@ by passing the html5 option:
1049
1141
  <%= f.input :expires_at, as: :date, html5: true %>
1050
1142
  ```
1051
1143
 
1144
+ ### Using non Active Record objects
1145
+
1146
+ There are few ways to build forms with objects that don't inherit from Active Record, as
1147
+ follow:
1148
+
1149
+ You can include the module `ActiveModel::Model`.
1150
+
1151
+ ```ruby
1152
+ class User
1153
+ include ActiveModel::Model
1154
+
1155
+ attr_accessor :id, :name
1156
+ end
1157
+ ```
1158
+
1159
+ If you are using Presenters or Decorators that inherit from `SimpleDelegator` you can delegate
1160
+ it to the model.
1161
+
1162
+ ```ruby
1163
+ class UserPresenter < SimpleDelegator
1164
+ # Without that, Simple Form will consider the user model as the object.
1165
+ def to_model
1166
+ self
1167
+ end
1168
+ end
1169
+ ```
1170
+
1171
+ You can define all methods required by the helpers.
1172
+
1173
+ ```ruby
1174
+ class User
1175
+ extend ActiveModel::Naming
1176
+
1177
+ attr_accessor :id, :name
1178
+
1179
+ def to_model
1180
+ self
1181
+ end
1182
+
1183
+ def to_key
1184
+ id
1185
+ end
1186
+
1187
+ def persisted?
1188
+ false
1189
+ end
1190
+ end
1191
+ ```
1192
+
1193
+ If your object doesn't implement those methods, you must make explicit it when you are
1194
+ building the form
1195
+
1196
+ ```ruby
1197
+ class User
1198
+ attr_accessor :id, :name
1199
+
1200
+ # The only method required to use the f.submit helper.
1201
+ def persisted?
1202
+ false
1203
+ end
1204
+ end
1205
+ ```
1206
+
1207
+ ```erb
1208
+ <%= simple_form_for(@user, as: :user, method: :post, url: users_path) do |f| %>
1209
+ <%= f.input :name %>
1210
+ <%= f.submit 'New user' %>
1211
+ <% end %>
1212
+ ```
1213
+
1052
1214
  ## Information
1053
1215
 
1054
1216
  ### Google Group
@@ -3,9 +3,9 @@
3
3
  Be sure to have a copy of the Bootstrap stylesheet available on your
4
4
  application, you can get it on http://getbootstrap.com/.
5
5
 
6
- Inside your views, use the 'simple_form_for' with one of the Bootstrap form
7
- classes, '.form-horizontal' or '.form-inline', as the following:
6
+ Inside your views, use the 'simple_form_for' with the Bootstrap form
7
+ class, '.form-inline', as the following:
8
8
 
9
- = simple_form_for(@user, html: { class: 'form-horizontal' }) do |form|
9
+ = simple_form_for(@user, html: { class: 'form-inline' }) do |form|
10
10
 
11
11
  ===============================================================================
@@ -1,6 +1,7 @@
1
1
  <%# frozen_string_literal: true %>
2
2
  <%%= simple_form_for(@<%= singular_table_name %>) do |f| %>
3
3
  <%%= f.error_notification %>
4
+ <%%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
4
5
 
5
6
  <div class="form-inputs">
6
7
  <%- attributes.each do |attribute| -%>
@@ -1,6 +1,7 @@
1
1
  -# frozen_string_literal: true
2
2
  = simple_form_for(@<%= singular_table_name %>) do |f|
3
3
  = f.error_notification
4
+ = f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
4
5
 
5
6
  .form-inputs
6
7
  <%- attributes.each do |attribute| -%>
@@ -1,5 +1,6 @@
1
1
  = simple_form_for(@<%= singular_table_name %>) do |f|
2
2
  = f.error_notification
3
+ = f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present?
3
4
 
4
5
  .form-inputs
5
6
  <%- attributes.each do |attribute| -%>
@@ -1,4 +1,11 @@
1
1
  # frozen_string_literal: true
2
+ #
3
+ # Uncomment this and change the path if necessary to include your own
4
+ # components.
5
+ # See https://github.com/plataformatec/simple_form#custom-components to know
6
+ # more about custom components.
7
+ # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8
+ #
2
9
  # Use this setup block to configure all options available in SimpleForm.
3
10
  SimpleForm.setup do |config|
4
11
  # Wrappers are used by the form builder to generate a
@@ -7,7 +14,7 @@ SimpleForm.setup do |config|
7
14
  # stack. The options given below are used to wrap the
8
15
  # whole input.
9
16
  config.wrappers :default, class: :input,
10
- hint_class: :field_with_hint, error_class: :field_with_errors do |b|
17
+ hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
11
18
  ## Extensions enabled by default
12
19
  # Any of these extensions can be disabled for a
13
20
  # given input by passing: `f.input EXTENSION_NAME => false`.
@@ -45,6 +52,7 @@ SimpleForm.setup do |config|
45
52
  b.optional :readonly
46
53
 
47
54
  ## Inputs
55
+ # b.use :input, class: 'input', error_class: 'is-invalid', valid_class: 'is-valid'
48
56
  b.use :label_input
49
57
  b.use :hint, wrap_with: { tag: :span, class: :hint }
50
58
  b.use :error, wrap_with: { tag: :span, class: :error }
@@ -125,7 +133,7 @@ SimpleForm.setup do |config|
125
133
  config.browser_validations = false
126
134
 
127
135
  # Collection of methods to detect if a file type was given.
128
- # config.file_methods = [ :mounted_as, :file?, :public_filename ]
136
+ # config.file_methods = [ :mounted_as, :file?, :public_filename :attached? ]
129
137
 
130
138
  # Custom mappings for input types. This should be a hash containing a regexp
131
139
  # to match as key, and the input type that will be used when the field name
@@ -167,4 +175,8 @@ SimpleForm.setup do |config|
167
175
 
168
176
  # Defines which i18n scope will be used in Simple Form.
169
177
  # config.i18n_scope = 'simple_form'
178
+
179
+ # Defines validation classes to the input_field. By default it's nil.
180
+ # config.input_field_valid_class = 'is-valid'
181
+ # config.input_field_error_class = 'is-invalid'
170
182
  end
@@ -1,11 +1,55 @@
1
1
  # frozen_string_literal: true
2
+
3
+ # Please do not make direct changes to this file!
4
+ # This generator is maintained by the community around simple_form-bootstrap:
5
+ # https://github.com/rafaelfranca/simple_form-bootstrap
6
+ # All future development, tests, and organization should happen there.
7
+ # Background history: https://github.com/plataformatec/simple_form/issues/1561
8
+
9
+ # Uncomment this and change the path if necessary to include your own
10
+ # components.
11
+ # See https://github.com/plataformatec/simple_form#custom-components
12
+ # to know more about custom components.
13
+ # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
14
+
2
15
  # Use this setup block to configure all options available in SimpleForm.
3
16
  SimpleForm.setup do |config|
17
+ # Default class for buttons
18
+ config.button_class = 'btn'
19
+
20
+ # Define the default class of the input wrapper of the boolean input.
21
+ config.boolean_label_class = 'form-check-label'
22
+
23
+ # How the label text should be generated altogether with the required text.
24
+ config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }
25
+
26
+ # Define the way to render check boxes / radio buttons with labels.
27
+ config.boolean_style = :inline
28
+
29
+ # You can wrap each item in a collection of radio/check boxes with a tag
30
+ config.item_wrapper_tag = :div
31
+
32
+ # Defines if the default input wrapper class should be included in radio
33
+ # collection wrappers.
34
+ config.include_default_input_wrapper_class = false
35
+
36
+ # CSS class to add for error notification helper.
4
37
  config.error_notification_class = 'alert alert-danger'
5
- config.button_class = 'btn btn-default'
6
- config.boolean_label_class = nil
7
38
 
8
- config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
39
+ # Method used to tidy up errors. Specify any Rails Array method.
40
+ # :first lists the first message for each field.
41
+ # :to_sentence to list all errors for each field.
42
+ config.error_method = :to_sentence
43
+
44
+ # add validation classes to `input_field`
45
+ config.input_field_error_class = 'is-invalid'
46
+ config.input_field_valid_class = 'is-valid'
47
+
48
+
49
+ # vertical forms
50
+ #
51
+ # vertical default_wrapper
52
+ config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
9
53
  b.use :html5
10
54
  b.use :placeholder
11
55
  b.optional :maxlength
@@ -13,48 +57,90 @@ SimpleForm.setup do |config|
13
57
  b.optional :pattern
14
58
  b.optional :min_max
15
59
  b.optional :readonly
16
- b.use :label, class: 'control-label'
60
+ b.use :label, class: 'form-control-label'
61
+ b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
62
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
63
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
64
+ end
65
+
66
+ # vertical input for boolean
67
+ config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
68
+ b.use :html5
69
+ b.optional :readonly
70
+ b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
71
+ bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
72
+ bb.use :label, class: 'form-check-label'
73
+ bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
74
+ bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
75
+ end
76
+ end
77
+
78
+ # vertical input for radio buttons and check boxes
79
+ 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|
80
+ b.use :html5
81
+ b.optional :readonly
82
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
83
+ ba.use :label_text
84
+ end
85
+ b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
86
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
87
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
88
+ end
17
89
 
18
- b.use :input, class: 'form-control'
19
- b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
20
- b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
90
+ # vertical input for inline radio buttons and check boxes
91
+ 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|
92
+ b.use :html5
93
+ b.optional :readonly
94
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
95
+ ba.use :label_text
96
+ end
97
+ b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
98
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
99
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
21
100
  end
22
101
 
23
- config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
102
+ # vertical file input
103
+ config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
24
104
  b.use :html5
25
105
  b.use :placeholder
26
106
  b.optional :maxlength
27
107
  b.optional :minlength
28
108
  b.optional :readonly
29
- b.use :label, class: 'control-label'
30
-
31
- b.use :input
32
- b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
33
- b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
109
+ b.use :label
110
+ b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid'
111
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
112
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
34
113
  end
35
114
 
36
- config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
115
+ # vertical multi select
116
+ config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
37
117
  b.use :html5
38
118
  b.optional :readonly
39
-
40
- b.wrapper tag: 'div', class: 'checkbox' do |ba|
41
- ba.use :label_input
119
+ b.use :label, class: 'form-control-label'
120
+ b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
121
+ ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
42
122
  end
43
-
44
- b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
45
- b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
123
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
124
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
46
125
  end
47
126
 
48
- config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
127
+ # vertical range input
128
+ config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
49
129
  b.use :html5
130
+ b.use :placeholder
50
131
  b.optional :readonly
51
- b.use :label, class: 'control-label'
52
- b.use :input
53
- b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
54
- b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
132
+ b.optional :step
133
+ b.use :label
134
+ b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
135
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
136
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
55
137
  end
56
138
 
57
- config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
139
+
140
+ # horizontal forms
141
+ #
142
+ # horizontal default_wrapper
143
+ config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
58
144
  b.use :html5
59
145
  b.use :placeholder
60
146
  b.optional :maxlength
@@ -62,58 +148,243 @@ SimpleForm.setup do |config|
62
148
  b.optional :pattern
63
149
  b.optional :min_max
64
150
  b.optional :readonly
65
- b.use :label, class: 'col-sm-3 control-label'
151
+ b.use :label, class: 'col-sm-3 col-form-label'
152
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
153
+ ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
154
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
155
+ ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
156
+ end
157
+ end
158
+
159
+ # horizontal input for boolean
160
+ config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
161
+ b.use :html5
162
+ b.optional :readonly
163
+ b.wrapper tag: 'label', class: 'col-sm-3' do |ba|
164
+ ba.use :label_text
165
+ end
166
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr|
167
+ wr.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
168
+ bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
169
+ bb.use :label, class: 'form-check-label'
170
+ bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
171
+ bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
172
+ end
173
+ end
174
+ end
175
+
176
+ # horizontal input for radio buttons and check boxes
177
+ 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|
178
+ b.use :html5
179
+ b.optional :readonly
180
+ b.use :label, class: 'col-sm-3 form-control-label'
181
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
182
+ ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
183
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
184
+ ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
185
+ end
186
+ end
66
187
 
67
- b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
68
- ba.use :input, class: 'form-control'
69
- ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
70
- ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
188
+ # horizontal input for inline radio buttons and check boxes
189
+ 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|
190
+ b.use :html5
191
+ b.optional :readonly
192
+ b.use :label, class: 'col-sm-3 form-control-label'
193
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
194
+ ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
195
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
196
+ ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
71
197
  end
72
198
  end
73
199
 
74
- config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
200
+ # horizontal file input
201
+ config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
75
202
  b.use :html5
76
203
  b.use :placeholder
77
204
  b.optional :maxlength
78
205
  b.optional :minlength
79
206
  b.optional :readonly
207
+ b.use :label, class: 'col-sm-3 form-control-label'
208
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
209
+ ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
210
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
211
+ ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
212
+ end
213
+ end
214
+
215
+ # horizontal multi select
216
+ config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
217
+ b.use :html5
218
+ b.optional :readonly
80
219
  b.use :label, class: 'col-sm-3 control-label'
220
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
221
+ ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
222
+ bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
223
+ end
224
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
225
+ ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
226
+ end
227
+ end
81
228
 
82
- b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
83
- ba.use :input
84
- ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
85
- ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
229
+ # horizontal range input
230
+ config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
231
+ b.use :html5
232
+ b.use :placeholder
233
+ b.optional :readonly
234
+ b.optional :step
235
+ b.use :label, class: 'col-sm-3 form-control-label'
236
+ b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
237
+ ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
238
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
239
+ ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
86
240
  end
87
241
  end
88
242
 
89
- config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
243
+
244
+ # inline forms
245
+ #
246
+ # inline default_wrapper
247
+ config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
90
248
  b.use :html5
249
+ b.use :placeholder
250
+ b.optional :maxlength
251
+ b.optional :minlength
252
+ b.optional :pattern
253
+ b.optional :min_max
91
254
  b.optional :readonly
255
+ b.use :label, class: 'sr-only'
92
256
 
93
- b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
94
- wr.wrapper tag: 'div', class: 'checkbox' do |ba|
95
- ba.use :label_input
96
- end
257
+ b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
258
+ b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
259
+ b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
260
+ end
261
+
262
+ # inline input for boolean
263
+ 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|
264
+ b.use :html5
265
+ b.optional :readonly
266
+ b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
267
+ b.use :label, class: 'form-check-label'
268
+ b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
269
+ b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
270
+ end
271
+
272
+
273
+ # bootstrap custom forms
274
+ #
275
+ # custom input for boolean
276
+ config.wrappers :custom_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
277
+ b.use :html5
278
+ b.optional :readonly
279
+ b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb|
280
+ bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
281
+ bb.use :label, class: 'custom-control-label'
282
+ bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
283
+ bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
284
+ end
285
+ end
97
286
 
98
- wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
99
- wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
287
+ config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
288
+ b.use :html5
289
+ b.optional :readonly
290
+ b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox-switch' do |bb|
291
+ bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
292
+ bb.use :label, class: 'custom-control-label'
293
+ bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
294
+ bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
100
295
  end
101
296
  end
102
297
 
103
- config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
298
+ # custom input for radio buttons and check boxes
299
+ 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|
104
300
  b.use :html5
105
301
  b.optional :readonly
302
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
303
+ ba.use :label_text
304
+ end
305
+ b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
306
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
307
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
308
+ end
106
309
 
107
- b.use :label, class: 'col-sm-3 control-label'
310
+ # custom input for inline radio buttons and check boxes
311
+ 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|
312
+ b.use :html5
313
+ b.optional :readonly
314
+ b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
315
+ ba.use :label_text
316
+ end
317
+ b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
318
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
319
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
320
+ end
321
+
322
+ # custom file input
323
+ config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
324
+ b.use :html5
325
+ b.use :placeholder
326
+ b.optional :maxlength
327
+ b.optional :minlength
328
+ b.optional :readonly
329
+ b.use :label, class: 'form-control-label'
330
+ b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
331
+ ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
332
+ ba.use :label, class: 'custom-file-label'
333
+ ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
334
+ end
335
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
336
+ end
108
337
 
109
- b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
110
- ba.use :input
111
- ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
112
- ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
338
+ # custom multi select
339
+ config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
340
+ b.use :html5
341
+ b.optional :readonly
342
+ b.use :label, class: 'form-control-label'
343
+ b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
344
+ ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
113
345
  end
346
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
347
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
348
+ end
349
+
350
+ # custom range input
351
+ config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
352
+ b.use :html5
353
+ b.use :placeholder
354
+ b.optional :readonly
355
+ b.optional :step
356
+ b.use :label, class: 'form-control-label'
357
+ b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
358
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
359
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
114
360
  end
115
361
 
116
- config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
362
+
363
+ # Input Group - custom component
364
+ # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
365
+ # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
366
+ # b.use :html5
367
+ # b.use :placeholder
368
+ # b.optional :maxlength
369
+ # b.optional :minlength
370
+ # b.optional :pattern
371
+ # b.optional :min_max
372
+ # b.optional :readonly
373
+ # b.use :label, class: 'form-control-label'
374
+ # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
375
+ # ba.optional :prepend
376
+ # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
377
+ # ba.optional :append
378
+ # end
379
+ # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
380
+ # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
381
+ # end
382
+
383
+
384
+ # Floating Labels form
385
+ #
386
+ # floating labels default_wrapper
387
+ config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
117
388
  b.use :html5
118
389
  b.use :placeholder
119
390
  b.optional :maxlength
@@ -121,35 +392,48 @@ SimpleForm.setup do |config|
121
392
  b.optional :pattern
122
393
  b.optional :min_max
123
394
  b.optional :readonly
124
- b.use :label, class: 'sr-only'
125
-
126
- b.use :input, class: 'form-control'
127
- b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
128
- b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
395
+ b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
396
+ b.use :label, class: 'form-control-label'
397
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
398
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
129
399
  end
130
400
 
131
- config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
401
+ # custom multi select
402
+ config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
132
403
  b.use :html5
133
404
  b.optional :readonly
134
- b.use :label, class: 'control-label'
135
- b.wrapper tag: 'div', class: 'form-inline' do |ba|
136
- ba.use :input, class: 'form-control'
137
- ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
138
- ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
139
- end
405
+ b.use :input, class: 'custom-select custom-select-lg', error_class: 'is-invalid', valid_class: 'is-valid'
406
+ b.use :label, class: 'form-control-label'
407
+ b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
408
+ b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
140
409
  end
141
- # Wrappers for forms and inputs using the Bootstrap toolkit.
142
- # Check the Bootstrap docs (http://getbootstrap.com)
143
- # to learn about the different styles for forms and inputs,
144
- # buttons and other elements.
410
+
411
+
412
+ # The default wrapper to be used by the FormBuilder.
145
413
  config.default_wrapper = :vertical_form
414
+
415
+ # Custom wrappers for input types. This should be a hash containing an input
416
+ # type as key and the wrapper that will be used for all inputs with specified type.
146
417
  config.wrapper_mappings = {
147
- check_boxes: :vertical_radio_and_checkboxes,
148
- radio_buttons: :vertical_radio_and_checkboxes,
149
- file: :vertical_file_input,
150
- boolean: :vertical_boolean,
151
- datetime: :multi_select,
152
- date: :multi_select,
153
- time: :multi_select
418
+ boolean: :vertical_boolean,
419
+ check_boxes: :vertical_collection,
420
+ date: :vertical_multi_select,
421
+ datetime: :vertical_multi_select,
422
+ file: :vertical_file,
423
+ radio_buttons: :vertical_collection,
424
+ range: :vertical_range,
425
+ time: :vertical_multi_select
154
426
  }
427
+
428
+ # enable custom form wrappers
429
+ # config.wrapper_mappings = {
430
+ # boolean: :custom_boolean,
431
+ # check_boxes: :custom_collection,
432
+ # date: :custom_multi_select,
433
+ # datetime: :custom_multi_select,
434
+ # file: :custom_file,
435
+ # radio_buttons: :custom_collection,
436
+ # range: :custom_range,
437
+ # time: :custom_multi_select
438
+ # }
155
439
  end