bootstrap_form 5.0.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +31 -16
- data/.gitignore +15 -3
- data/.rubocop.yml +3 -1
- data/.yarnrc +5 -0
- data/CHANGELOG.md +53 -2
- data/CONTRIBUTING.md +110 -22
- data/Dangerfile +5 -5
- data/Dockerfile +6 -11
- data/Gemfile +5 -23
- data/README.md +805 -54
- data/RELEASING.md +16 -10
- data/Rakefile +7 -6
- data/bootstrap_form.gemspec +7 -10
- data/docker-compose.yml +9 -48
- data/gemfiles/6.0.gemfile +1 -1
- data/gemfiles/6.1.gemfile +1 -1
- data/gemfiles/7.0.gemfile +5 -0
- data/gemfiles/common.gemfile +28 -0
- data/gemfiles/edge.gemfile +3 -2
- data/lib/bootstrap_form/components/hints.rb +13 -4
- data/lib/bootstrap_form/components/labels.rb +4 -10
- data/lib/bootstrap_form/components/validation.rb +36 -19
- data/lib/bootstrap_form/form_builder.rb +9 -6
- data/lib/bootstrap_form/form_group.rb +15 -8
- data/lib/bootstrap_form/form_group_builder.rb +10 -7
- data/lib/bootstrap_form/helpers/bootstrap.rb +12 -9
- data/lib/bootstrap_form/helpers/field.rb +26 -0
- data/lib/bootstrap_form/helpers.rb +1 -0
- data/lib/bootstrap_form/inputs/check_box.rb +26 -8
- data/lib/bootstrap_form/inputs/collection_check_boxes.rb +5 -1
- data/lib/bootstrap_form/inputs/collection_select.rb +1 -1
- data/lib/bootstrap_form/inputs/grouped_collection_select.rb +1 -1
- data/lib/bootstrap_form/inputs/radio_button.rb +15 -10
- data/lib/bootstrap_form/version.rb +2 -1
- data/lib/bootstrap_form.rb +1 -1
- metadata +17 -88
- data/demo/.postcssrc.yml +0 -3
- data/demo/README.md +0 -17
- data/demo/Rakefile +0 -6
- data/demo/app/assets/config/manifest.js +0 -1
- data/demo/app/assets/stylesheets/actiontext.scss +0 -38
- data/demo/app/assets/stylesheets/application.scss +0 -1
- data/demo/app/controllers/application_controller.rb +0 -2
- data/demo/app/controllers/bootstrap_controller.rb +0 -14
- data/demo/app/helpers/bootstrap_helper.rb +0 -27
- data/demo/app/javascript/channels/consumer.js +0 -6
- data/demo/app/javascript/channels/index.js +0 -5
- data/demo/app/javascript/packs/application.js +0 -11
- data/demo/app/models/address.rb +0 -3
- data/demo/app/models/application_record.rb +0 -3
- data/demo/app/models/faux_user.rb +0 -9
- data/demo/app/models/super_user.rb +0 -2
- data/demo/app/models/user.rb +0 -11
- data/demo/app/views/active_storage/blobs/_blob.html.erb +0 -14
- data/demo/app/views/bootstrap/form.html.erb +0 -67
- data/demo/app/views/layouts/application.html.erb +0 -68
- data/demo/bin/bundle +0 -3
- data/demo/bin/rails +0 -4
- data/demo/bin/rake +0 -4
- data/demo/bin/setup +0 -36
- data/demo/bin/update +0 -31
- data/demo/bin/webpack +0 -15
- data/demo/bin/webpack-dev-server +0 -15
- data/demo/bin/yarn +0 -11
- data/demo/config/application.rb +0 -21
- data/demo/config/boot.rb +0 -5
- data/demo/config/database.yml +0 -21
- data/demo/config/environment.rb +0 -5
- data/demo/config/environments/development.rb +0 -60
- data/demo/config/environments/production.rb +0 -48
- data/demo/config/environments/test.rb +0 -46
- data/demo/config/initializers/application_controller_renderer.rb +0 -8
- data/demo/config/initializers/assets.rb +0 -14
- data/demo/config/initializers/backtrace_silencers.rb +0 -7
- data/demo/config/initializers/cookies_serializer.rb +0 -5
- data/demo/config/initializers/filter_parameter_logging.rb +0 -4
- data/demo/config/initializers/inflections.rb +0 -16
- data/demo/config/initializers/mime_types.rb +0 -4
- data/demo/config/initializers/wrap_parameters.rb +0 -14
- data/demo/config/locales/en.yml +0 -33
- data/demo/config/puma.rb +0 -56
- data/demo/config/routes.rb +0 -5
- data/demo/config/spring.rb +0 -6
- data/demo/config/storage.yml +0 -35
- data/demo/config/webpack/development.js +0 -5
- data/demo/config/webpack/environment.js +0 -3
- data/demo/config/webpack/production.js +0 -5
- data/demo/config/webpack/test.js +0 -5
- data/demo/config/webpacker.yml +0 -92
- data/demo/config.ru +0 -5
- data/demo/db/schema.rb +0 -69
- data/demo/log/.keep +0 -0
- data/demo/package.json +0 -17
- data/demo/public/favicon.ico +0 -0
- data/demo/test/fixtures/action_text/rich_texts.yml +0 -4
- data/demo/yarn.lock +0 -6257
- data/gemfiles/5.2.gemfile +0 -4
data/README.md
CHANGED
@@ -25,16 +25,24 @@ Some other nice things that `bootstrap_form` does for you are:
|
|
25
25
|
|
26
26
|
`bootstrap_form` supports at a minimum the currently supported versions of Ruby and Rails:
|
27
27
|
|
28
|
-
* Ruby
|
29
|
-
* Rails
|
28
|
+
* Ruby 3.0+ (https://www.ruby-lang.org/en/downloads/branches/)
|
29
|
+
* Rails 6.0+ (https://guides.rubyonrails.org/maintenance_policy.html)
|
30
30
|
* Bootstrap 5.0+
|
31
31
|
|
32
32
|
## Installation
|
33
33
|
|
34
|
-
|
34
|
+
Install Bootstrap 5. There are many ways to do this, depending on the asset pipeline you're using in your Rails application. One way is to use the gem that works with Sprockets. To do so, in a brand new Rails 7.0 application created _without_ the `--webpacker` option, add the `bootstrap` gem to your `Gemfile`:
|
35
35
|
|
36
36
|
```ruby
|
37
|
-
gem "
|
37
|
+
gem "bootstrap", "~> 5.0"
|
38
|
+
```
|
39
|
+
|
40
|
+
And follow the remaining instructions in the [official bootstrap installation guide](https://github.com/twbs/bootstrap-rubygem#a-ruby-on-rails) for setting up `application.scss` and `application.js`.
|
41
|
+
|
42
|
+
Add the `bootstrap_form` gem to your `Gemfile`:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
gem "bootstrap_form", "~> 5.2"
|
38
46
|
```
|
39
47
|
|
40
48
|
Then:
|
@@ -60,6 +68,7 @@ If you followed the [official bootstrap installation guide](https://github.com/t
|
|
60
68
|
|
61
69
|
To get started, use the `bootstrap_form_for` helper in place of the Rails `form_for` helper. Here's an example:
|
62
70
|
|
71
|
+
![Example 0](demo/doc/screenshots/bootstrap/readme/00_example.png "Example 0")
|
63
72
|
```erb
|
64
73
|
<%= bootstrap_form_for(@user) do |f| %>
|
65
74
|
<%= f.email_field :email %>
|
@@ -74,19 +83,19 @@ This generates the following HTML:
|
|
74
83
|
```html
|
75
84
|
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
76
85
|
<div class="mb-3">
|
77
|
-
<label class="form-label" for="user_email">Email</label>
|
78
|
-
<input class="form-control" id="user_email" name="user[email]" type="email">
|
86
|
+
<label class="form-label required" for="user_email">Email</label>
|
87
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
79
88
|
</div>
|
80
89
|
<div class="mb-3">
|
81
90
|
<label class="form-label" for="user_password">Password</label>
|
82
91
|
<input class="form-control" id="user_password" name="user[password]" type="password">
|
83
92
|
</div>
|
84
|
-
<div class="form-check">
|
85
|
-
<input name="user[remember_me]" type="hidden" value="0">
|
93
|
+
<div class="form-check mb-3">
|
94
|
+
<input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
|
86
95
|
<input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
|
87
96
|
<label class="form-check-label" for="user_remember_me">Remember me</label>
|
88
97
|
</div>
|
89
|
-
<input class="btn btn-secondary" name="commit" type="submit" value="Log In">
|
98
|
+
<input class="btn btn-secondary" data-disable-with="Log In" name="commit" type="submit" value="Log In">
|
90
99
|
</form>
|
91
100
|
```
|
92
101
|
|
@@ -94,6 +103,7 @@ This generates the following HTML:
|
|
94
103
|
|
95
104
|
If your form is not backed by a model, use the `bootstrap_form_tag`. Usage of this helper is the same as `bootstrap_form_for`, except no model object is passed in as the first argument. Here's an example:
|
96
105
|
|
106
|
+
![Example 1](demo/doc/screenshots/bootstrap/readme/01_example.png "Example 1")
|
97
107
|
```erb
|
98
108
|
<%= bootstrap_form_tag url: '/subscribe' do |f| %>
|
99
109
|
<%= f.email_field :email, value: 'name@example.com' %>
|
@@ -101,16 +111,29 @@ If your form is not backed by a model, use the `bootstrap_form_tag`. Usage of th
|
|
101
111
|
<% end %>
|
102
112
|
```
|
103
113
|
|
114
|
+
This generates:
|
115
|
+
|
116
|
+
```html
|
117
|
+
<form accept-charset="UTF-8" action="/subscribe" method="post">
|
118
|
+
<div class="mb-3">
|
119
|
+
<label class="form-label" for="email">Email</label>
|
120
|
+
<input class="form-control" id="email" name="email" type="email" value="name@example.com">
|
121
|
+
</div>
|
122
|
+
<input class="btn btn-secondary" data-disable-with="Save " name="commit" type="submit" value="Save ">
|
123
|
+
</form>
|
124
|
+
```
|
125
|
+
|
104
126
|
### bootstrap_form_with
|
105
127
|
|
106
128
|
Note that `form_with` in Rails 5.1 does not add IDs to form elements and labels by default, which are both important to Bootstrap markup. This behaviour is corrected in Rails 5.2.
|
107
129
|
|
108
130
|
To get started, just use the `bootstrap_form_with` helper in place of `form_with`. Here's an example:
|
109
131
|
|
132
|
+
![Example 2](demo/doc/screenshots/bootstrap/readme/02_example.png "Example 2")
|
110
133
|
```erb
|
111
134
|
<%= bootstrap_form_with(model: @user, local: true) do |f| %>
|
112
135
|
<%= f.email_field :email %>
|
113
|
-
<%= f.password_field :password %>
|
136
|
+
<%= f.password_field :password, help: 'A good password should be at least six characters long' %>
|
114
137
|
<%= f.check_box :remember_me %>
|
115
138
|
<%= f.submit "Log In" %>
|
116
139
|
<% end %>
|
@@ -119,23 +142,22 @@ To get started, just use the `bootstrap_form_with` helper in place of `form_with
|
|
119
142
|
This generates:
|
120
143
|
|
121
144
|
```html
|
122
|
-
<form
|
123
|
-
<input name="utf8" type="hidden" value="✓" />
|
145
|
+
<form accept-charset="UTF-8" action="/users" method="post">
|
124
146
|
<div class="mb-3">
|
125
147
|
<label class="form-label required" for="user_email">Email</label>
|
126
|
-
<input class="form-control" type="email" value="steve@example.com"
|
148
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
127
149
|
</div>
|
128
150
|
<div class="mb-3">
|
129
151
|
<label class="form-label" for="user_password">Password</label>
|
130
|
-
<input class="form-control"
|
152
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
131
153
|
<small class="form-text text-muted">A good password should be at least six characters long</small>
|
132
154
|
</div>
|
133
|
-
<div class="form-check">
|
134
|
-
<input name="user[remember_me]" type="hidden" value="0">
|
155
|
+
<div class="form-check mb-3">
|
156
|
+
<input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
|
135
157
|
<input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
|
136
158
|
<label class="form-check-label" for="user_remember_me">Remember me</label>
|
137
159
|
</div>
|
138
|
-
<input
|
160
|
+
<input class="btn btn-secondary" data-disable-with="Log In" name="commit" type="submit" value="Log In">
|
139
161
|
</form>
|
140
162
|
```
|
141
163
|
|
@@ -212,41 +234,93 @@ The options for the form helpers that aren't in the exceptions list are describe
|
|
212
234
|
|
213
235
|
Use the `label` option if you want to specify the field's label text:
|
214
236
|
|
237
|
+
![Example 3](demo/doc/screenshots/bootstrap/readme/03_example.png "Example 3")
|
215
238
|
```erb
|
216
239
|
<%= f.password_field :password_confirmation, label: "Confirm Password" %>
|
217
240
|
```
|
218
241
|
|
219
|
-
|
242
|
+
This generates:
|
243
|
+
|
244
|
+
```html
|
245
|
+
<div class="mb-3">
|
246
|
+
<label class="form-label" for="user_password_confirmation">Confirm Password</label>
|
247
|
+
<input class="form-control" id="user_password_confirmation" name="user[password_confirmation]" type="password">
|
248
|
+
</div>
|
249
|
+
```
|
250
|
+
|
251
|
+
To hide a label, use the `hide_label: true` option. This adds the `visually-hidden`
|
220
252
|
class, which keeps your labels accessible to those using screen readers.
|
221
253
|
|
254
|
+
![Example 4](demo/doc/screenshots/bootstrap/readme/04_example.png "Example 4")
|
222
255
|
```erb
|
223
256
|
<%= f.text_area :comment, hide_label: true, placeholder: "Leave a comment..." %>
|
224
257
|
```
|
225
258
|
|
259
|
+
This generates:
|
260
|
+
|
261
|
+
```html
|
262
|
+
<div class="mb-3">
|
263
|
+
<label class="form-label visually-hidden" for="user_comment">Comment</label>
|
264
|
+
<textarea class="form-control" id="user_comment" name="user[comment]" placeholder="Leave a comment...">
|
265
|
+
</textarea>
|
266
|
+
</div>
|
267
|
+
```
|
268
|
+
|
226
269
|
To add custom classes to the field's label:
|
227
270
|
|
271
|
+
![Example 5](demo/doc/screenshots/bootstrap/readme/05_example.png "Example 5")
|
228
272
|
```erb
|
229
273
|
<%= f.text_field :email, label_class: "custom-class" %>
|
230
274
|
```
|
231
275
|
|
276
|
+
This generates:
|
277
|
+
|
278
|
+
```html
|
279
|
+
<div class="mb-3">
|
280
|
+
<label class="form-label custom-class required" for="user_email">Email</label>
|
281
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="text" value="steve@example.com">
|
282
|
+
</div>
|
283
|
+
```
|
284
|
+
|
232
285
|
Or you can add the label as input placeholder instead (this automatically hides the label):
|
233
286
|
|
287
|
+
![Example 6](demo/doc/screenshots/bootstrap/readme/06_example.png "Example 6")
|
234
288
|
```erb
|
235
289
|
<%= f.text_field :email, label_as_placeholder: true %>
|
236
290
|
```
|
237
291
|
|
292
|
+
This generates:
|
293
|
+
|
294
|
+
```html
|
295
|
+
<div class="mb-3">
|
296
|
+
<label class="form-label visually-hidden required" for="user_email">Email</label>
|
297
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" placeholder="Email" required="required" type="text" value="steve@example.com">
|
298
|
+
</div>
|
299
|
+
```
|
300
|
+
|
238
301
|
### Input Elements / Controls
|
239
302
|
|
240
303
|
To specify the class of the generated input tag, use the `control_class` option:
|
241
304
|
|
305
|
+
![Example 7](demo/doc/screenshots/bootstrap/readme/07_example.png "Example 7")
|
242
306
|
```erb
|
243
307
|
<%= f.text_field :email, control_class: "custom-class" %>
|
244
308
|
```
|
245
309
|
|
310
|
+
This generates:
|
311
|
+
|
312
|
+
```html
|
313
|
+
<div class="mb-3">
|
314
|
+
<label class="form-label required" for="user_email">Email</label>
|
315
|
+
<input aria-required="true" class="custom-class" id="user_email" name="user[email]" required="required" type="text" value="steve@example.com">
|
316
|
+
</div>
|
317
|
+
```
|
318
|
+
|
246
319
|
### Help Text
|
247
320
|
|
248
321
|
To add help text, use the `help` option:
|
249
322
|
|
323
|
+
![Example 8](demo/doc/screenshots/bootstrap/readme/08_example.png "Example 8")
|
250
324
|
```erb
|
251
325
|
<%= f.password_field :password, help: "Must be at least 6 characters long" %>
|
252
326
|
```
|
@@ -254,7 +328,11 @@ To add help text, use the `help` option:
|
|
254
328
|
This generates:
|
255
329
|
|
256
330
|
```html
|
257
|
-
<
|
331
|
+
<div class="mb-3">
|
332
|
+
<label class="form-label" for="user_password">Password</label>
|
333
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
334
|
+
<small class="form-text text-muted">Must be at least 6 characters long</small>
|
335
|
+
</div>
|
258
336
|
```
|
259
337
|
|
260
338
|
This gem is also aware of help messages in locale translation files (i18n):
|
@@ -287,41 +365,108 @@ option or turn them off completely by passing `help: false`.
|
|
287
365
|
|
288
366
|
You can pass `prepend` and/or `append` options to input fields:
|
289
367
|
|
368
|
+
![Example 9](demo/doc/screenshots/bootstrap/readme/09_example.png "Example 9")
|
290
369
|
```erb
|
291
370
|
<%= f.text_field :price, prepend: "$", append: ".00" %>
|
292
371
|
```
|
293
372
|
|
373
|
+
This generates:
|
374
|
+
|
375
|
+
```html
|
376
|
+
<div class="mb-3">
|
377
|
+
<label class="form-label" for="user_price">Price</label>
|
378
|
+
<div class="input-group">
|
379
|
+
<span class="input-group-text">$</span>
|
380
|
+
<input class="form-control" id="user_price" name="user[price]" type="text">
|
381
|
+
<span class="input-group-text">.00</span>
|
382
|
+
</div>
|
383
|
+
</div>
|
384
|
+
```
|
385
|
+
|
294
386
|
If you want to attach multiple items to the input, pass them as an array:
|
295
387
|
|
388
|
+
![Example 10](demo/doc/screenshots/bootstrap/readme/10_example.png "Example 10")
|
296
389
|
```erb
|
297
390
|
<%= f.text_field :price, prepend: ['Net', '$'], append: ['.00', 'per day'] %>
|
298
391
|
```
|
299
392
|
|
393
|
+
This generates:
|
394
|
+
|
395
|
+
```html
|
396
|
+
<div class="mb-3">
|
397
|
+
<label class="form-label" for="user_price">Price</label>
|
398
|
+
<div class="input-group">
|
399
|
+
<span class="input-group-text">Net</span>
|
400
|
+
<span class="input-group-text">$</span>
|
401
|
+
<input class="form-control" id="user_price" name="user[price]" type="text">
|
402
|
+
<span class="input-group-text">.00</span>
|
403
|
+
<span class="input-group-text">per day</span>
|
404
|
+
</div>
|
405
|
+
</div>
|
406
|
+
```
|
407
|
+
|
300
408
|
You can also prepend and append buttons. Note: The buttons must contain the
|
301
409
|
`btn` class to generate the correct markup.
|
302
410
|
|
411
|
+
![Example 11](demo/doc/screenshots/bootstrap/readme/11_example.png "Example 11")
|
303
412
|
```erb
|
304
413
|
<%= f.text_field :search, append: link_to("Go", "#", class: "btn btn-secondary") %>
|
305
414
|
```
|
306
415
|
|
416
|
+
This generates:
|
417
|
+
|
418
|
+
```html
|
419
|
+
<div class="mb-3">
|
420
|
+
<label class="form-label" for="user_search">Search</label>
|
421
|
+
<div class="input-group">
|
422
|
+
<input class="form-control" id="user_search" name="user[search]" type="text">
|
423
|
+
<a class="btn btn-secondary" href="#">Go</a>
|
424
|
+
</div>
|
425
|
+
</div>
|
426
|
+
```
|
427
|
+
|
307
428
|
To add a class to the input group wrapper, use the `:input_group_class` option.
|
308
429
|
|
430
|
+
![Example 12](demo/doc/screenshots/bootstrap/readme/12_example.png "Example 12")
|
309
431
|
```erb
|
310
432
|
<%= f.email_field :email, append: f.primary('Subscribe'), input_group_class: 'input-group-lg' %>
|
311
433
|
```
|
312
434
|
|
435
|
+
This generates:
|
436
|
+
|
437
|
+
```html
|
438
|
+
<div class="mb-3">
|
439
|
+
<label class="form-label required" for="user_email">Email</label>
|
440
|
+
<div class="input-group input-group-lg">
|
441
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
442
|
+
<input class="btn btn-primary" data-disable-with="Subscribe" name="commit" type="submit" value="Subscribe">
|
443
|
+
</div>
|
444
|
+
</div>
|
445
|
+
```
|
446
|
+
|
313
447
|
### Additional Form Group Attributes
|
314
448
|
|
315
449
|
Bootstrap mark-up dictates that most input field types have the label and input wrapped in a `div.mb-3`.
|
316
450
|
|
317
|
-
If you want to
|
451
|
+
If you want to change the CSS class or any other attribute to the form group div, you can use the `wrapper: { class: 'mb-3 additional-class', data: { foo: 'bar' } }` option.
|
318
452
|
|
453
|
+
![Example 13](demo/doc/screenshots/bootstrap/readme/13_example.png "Example 13")
|
319
454
|
```erb
|
320
|
-
<%= f.text_field :name, wrapper: { class: 'has-warning', data: { foo: 'bar' } } %>
|
455
|
+
<%= f.text_field :name, wrapper: { class: 'mb-3 has-warning', data: { foo: 'bar' } } %>
|
456
|
+
```
|
457
|
+
|
458
|
+
This generates:
|
459
|
+
|
460
|
+
```html
|
461
|
+
<div class="mb-3 has-warning" data-foo="bar">
|
462
|
+
<label class="form-label" for="user_name">Name</label>
|
463
|
+
<input class="form-control" id="user_name" name="user[name]" type="text">
|
464
|
+
</div>
|
321
465
|
```
|
322
466
|
|
323
467
|
Which produces the following output:
|
324
468
|
|
469
|
+
![Example 14](demo/doc/screenshots/bootstrap/readme/14_example.png "Example 14")
|
325
470
|
```erb
|
326
471
|
<div class="mb-3 has-warning" data-foo="bar">
|
327
472
|
<label class="form-label form-control-label" for="user_name">Id</label>
|
@@ -329,16 +474,37 @@ Which produces the following output:
|
|
329
474
|
</div>
|
330
475
|
```
|
331
476
|
|
332
|
-
|
477
|
+
This generates:
|
478
|
+
|
479
|
+
```html
|
480
|
+
<div class="mb-3 has-warning" data-foo="bar">
|
481
|
+
<label class="form-label form-control-label" for="user_name">Id</label>
|
482
|
+
<input class="form-control" id="user_name" name="user[name]" type="text">
|
483
|
+
</div>
|
484
|
+
```
|
485
|
+
|
486
|
+
If you only want to set the class on the form group div, you can use the `wrapper_class` option: `wrapper_class: 'mb-3 additional-class'`.
|
487
|
+
It's just a short form of `wrapper: { class: 'mb-3 additional-class' }`.
|
488
|
+
|
489
|
+
If you don't want any class on the form group div, you can set it to `false`: `wrapper_class: false`.
|
333
490
|
|
334
491
|
### Suppressing the Form Group Altogether
|
335
492
|
|
336
493
|
You may want to define your own form group div around a field. To do so, add the option `wrapper: false` to the input field. For example:
|
337
494
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
495
|
+
![Example 15](demo/doc/screenshots/bootstrap/readme/15_example.png "Example 15")
|
496
|
+
```erb
|
497
|
+
<%= f.form_group :user do %>
|
498
|
+
<%= f.email_field :email, wrapper: false %>
|
499
|
+
<% end %>
|
500
|
+
```
|
501
|
+
|
502
|
+
Generated HTML:
|
503
|
+
|
504
|
+
```html
|
505
|
+
<div class="mb-3">
|
506
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
507
|
+
</div>
|
342
508
|
```
|
343
509
|
|
344
510
|
Note that Bootstrap relies on the form group div to correctly format most fields, so if you use the `wrapper: false` option, you should provide your own form group div around the input field. You can write your own HTML, or use the `form_group` helper.
|
@@ -347,16 +513,30 @@ Note that Bootstrap relies on the form group div to correctly format most fields
|
|
347
513
|
|
348
514
|
Our select helper accepts the same arguments as the [default Rails helper](http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select). Here's an example of how you pass both options and html_options hashes:
|
349
515
|
|
516
|
+
![Example 16](demo/doc/screenshots/bootstrap/readme/16_example.png "Example 16")
|
350
517
|
```erb
|
351
518
|
<%= f.select :product, [["Apple", 1], ["Grape", 2]], { label: "Choose your favorite fruit:", wrapper: { class: 'has-warning', data: { foo: 'bar' } } }, { class: "selectpicker" } %>
|
352
519
|
```
|
353
520
|
|
521
|
+
This generates:
|
522
|
+
|
523
|
+
```html
|
524
|
+
<div class="has-warning" data-foo="bar">
|
525
|
+
<label class="form-label" for="user_product">Choose your favorite fruit:</label>
|
526
|
+
<select class="form-select selectpicker" id="user_product" name="user[product]">
|
527
|
+
<option value="1">Apple</option>
|
528
|
+
<option value="2">Grape</option>
|
529
|
+
</select>
|
530
|
+
</div>
|
531
|
+
```
|
532
|
+
|
354
533
|
## Checkboxes and Radios
|
355
534
|
|
356
535
|
Checkboxes and radios should be placed inside of a `form_group` to render
|
357
536
|
properly. The following example ensures that the entire form group will display
|
358
537
|
an error if an associated validations fails:
|
359
538
|
|
539
|
+
![Example 17](demo/doc/screenshots/bootstrap/readme/17_example.png "Example 17")
|
360
540
|
```erb
|
361
541
|
<%= f.form_group :skill_level, label: { text: "Skill" }, help: "Optional Help Text" do %>
|
362
542
|
<%= f.radio_button :skill_level, 0, label: "Novice", checked: true %>
|
@@ -369,8 +549,37 @@ an error if an associated validations fails:
|
|
369
549
|
<% end %>
|
370
550
|
```
|
371
551
|
|
552
|
+
This generates:
|
553
|
+
|
554
|
+
```html
|
555
|
+
<div class="mb-3">
|
556
|
+
<label class="form-label" for="user_skill_level">Skill</label>
|
557
|
+
<div class="form-check">
|
558
|
+
<input checked class="form-check-input" id="user_skill_level_0" name="user[skill_level]" type="radio" value="0">
|
559
|
+
<label class="form-check-label" for="user_skill_level_0">Novice</label>
|
560
|
+
</div>
|
561
|
+
<div class="form-check">
|
562
|
+
<input class="form-check-input" id="user_skill_level_1" name="user[skill_level]" type="radio" value="1">
|
563
|
+
<label class="form-check-label" for="user_skill_level_1">Intermediate</label>
|
564
|
+
</div>
|
565
|
+
<div class="form-check">
|
566
|
+
<input class="form-check-input" id="user_skill_level_2" name="user[skill_level]" type="radio" value="2">
|
567
|
+
<label class="form-check-label" for="user_skill_level_2">Advanced</label>
|
568
|
+
</div>
|
569
|
+
<small class="form-text text-muted">Optional Help Text</small>
|
570
|
+
</div>
|
571
|
+
<div class="mb-3">
|
572
|
+
<div class="form-check mb-3">
|
573
|
+
<input autocomplete="off" name="user[terms]" type="hidden" value="0">
|
574
|
+
<input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1">
|
575
|
+
<label class="form-check-label" for="user_terms">I agree to the Terms of Service</label>
|
576
|
+
</div>
|
577
|
+
</div>
|
578
|
+
```
|
579
|
+
|
372
580
|
You can also create a checkbox using a block:
|
373
581
|
|
582
|
+
![Example 18](demo/doc/screenshots/bootstrap/readme/18_example.png "Example 18")
|
374
583
|
```erb
|
375
584
|
<%= f.form_group :terms, label: { text: "Optional Label" } do %>
|
376
585
|
<%= f.check_box :terms do %>
|
@@ -379,8 +588,24 @@ You can also create a checkbox using a block:
|
|
379
588
|
<% end %>
|
380
589
|
```
|
381
590
|
|
591
|
+
This generates:
|
592
|
+
|
593
|
+
```html
|
594
|
+
<div class="mb-3">
|
595
|
+
<label class="form-label" for="user_terms">Optional Label</label>
|
596
|
+
<div class="form-check mb-3">
|
597
|
+
<input autocomplete="off" name="user[terms]" type="hidden" value="0">
|
598
|
+
<input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1">
|
599
|
+
<label class="form-check-label" for="user_terms">
|
600
|
+
You need to check this box to accept our terms of service and privacy policy
|
601
|
+
</label>
|
602
|
+
</div>
|
603
|
+
</div>
|
604
|
+
```
|
605
|
+
|
382
606
|
To display checkboxes and radios inline, pass the `inline: true` option:
|
383
607
|
|
608
|
+
![Example 19](demo/doc/screenshots/bootstrap/readme/19_example.png "Example 19")
|
384
609
|
```erb
|
385
610
|
<%= f.form_group :skill_level, label: { text: "Skill" } do %>
|
386
611
|
<%= f.radio_button :skill_level, 0, label: "Novice", inline: true %>
|
@@ -389,30 +614,122 @@ To display checkboxes and radios inline, pass the `inline: true` option:
|
|
389
614
|
<% end %>
|
390
615
|
```
|
391
616
|
|
617
|
+
This generates:
|
618
|
+
|
619
|
+
```html
|
620
|
+
<div class="mb-3">
|
621
|
+
<label class="form-label" for="user_skill_level">Skill</label>
|
622
|
+
<div class="form-check form-check-inline">
|
623
|
+
<input class="form-check-input" id="user_skill_level_0" name="user[skill_level]" type="radio" value="0">
|
624
|
+
<label class="form-check-label" for="user_skill_level_0">Novice</label>
|
625
|
+
</div>
|
626
|
+
<div class="form-check form-check-inline">
|
627
|
+
<input class="form-check-input" id="user_skill_level_1" name="user[skill_level]" type="radio" value="1">
|
628
|
+
<label class="form-check-label" for="user_skill_level_1">Intermediate</label>
|
629
|
+
</div>
|
630
|
+
<div class="form-check form-check-inline">
|
631
|
+
<input class="form-check-input" id="user_skill_level_2" name="user[skill_level]" type="radio" value="2">
|
632
|
+
<label class="form-check-label" for="user_skill_level_2">Advanced</label>
|
633
|
+
</div>
|
634
|
+
</div>
|
635
|
+
```
|
636
|
+
|
392
637
|
Check boxes and radio buttons are wrapped in a `div.form-check`. You can add classes to this `div` with the `:wrapper_class` option:
|
393
638
|
|
639
|
+
![Example 20](demo/doc/screenshots/bootstrap/readme/20_example.png "Example 20")
|
394
640
|
```erb
|
395
641
|
<%= f.radio_button :skill_level, 0, label: "Novice", inline: true, wrapper_class: "w-auto" %>
|
396
642
|
```
|
397
643
|
|
644
|
+
This generates:
|
645
|
+
|
646
|
+
```html
|
647
|
+
<div class="form-check form-check-inline w-auto">
|
648
|
+
<input class="form-check-input" id="user_skill_level_0" name="user[skill_level]" type="radio" value="0">
|
649
|
+
<label class="form-check-label" for="user_skill_level_0">Novice</label>
|
650
|
+
</div>
|
651
|
+
```
|
652
|
+
|
653
|
+
You can also add a style to the tag using the `wrapper` option:
|
654
|
+
|
655
|
+
![Example 21](demo/doc/screenshots/bootstrap/readme/21_example.png "Example 21")
|
656
|
+
```erb
|
657
|
+
<%= f.check_box :skilled, inline: true, wrapper: {style: "color: green"} %>
|
658
|
+
<%= f.radio_button :skill_level, 0, label: "Novice", inline: true, wrapper: {class: 'w-auto', style: "color: red"} %>
|
659
|
+
```
|
660
|
+
|
661
|
+
This generates:
|
662
|
+
|
663
|
+
```html
|
664
|
+
<div class="form-check form-check-inline mb-3" style="color: green">
|
665
|
+
<input autocomplete="off" name="user[skilled]" type="hidden" value="0">
|
666
|
+
<input class="form-check-input" id="user_skilled" name="user[skilled]" type="checkbox" value="1">
|
667
|
+
<label class="form-check-label" for="user_skilled">Skilled</label>
|
668
|
+
</div>
|
669
|
+
<div class="form-check form-check-inline w-auto" style="color: red">
|
670
|
+
<input class="form-check-input" id="user_skill_level_0" name="user[skill_level]" type="radio" value="0">
|
671
|
+
<label class="form-check-label" for="user_skill_level_0">Novice</label>
|
672
|
+
</div>
|
673
|
+
```
|
674
|
+
|
398
675
|
### Switches
|
399
676
|
|
400
677
|
To render checkboxes as switches with Bootstrap 4.2+, use `switch: true`:
|
401
678
|
|
679
|
+
![Example 22](demo/doc/screenshots/bootstrap/readme/22_example.png "Example 22")
|
402
680
|
```erb
|
403
681
|
<%= f.check_box :remember_me, switch: true %>
|
404
682
|
```
|
405
683
|
|
684
|
+
This generates:
|
685
|
+
|
686
|
+
```html
|
687
|
+
<div class="form-check mb-3 form-switch">
|
688
|
+
<input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
|
689
|
+
<input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
|
690
|
+
<label class="form-check-label" for="user_remember_me">Remember me</label>
|
691
|
+
</div>
|
692
|
+
```
|
693
|
+
|
406
694
|
### Collections
|
407
695
|
|
408
696
|
`bootstrap_form` also provides helpers that automatically create the
|
409
697
|
`form_group` and the `radio_button`s or `check_box`es for you:
|
410
698
|
|
699
|
+
![Example 23](demo/doc/screenshots/bootstrap/readme/23_example.png "Example 23")
|
411
700
|
```erb
|
412
701
|
<%= f.collection_radio_buttons :skill_level, Skill.all, :id, :name %>
|
413
702
|
<%= f.collection_check_boxes :skills, Skill.all, :id, :name %>
|
414
703
|
```
|
415
704
|
|
705
|
+
This generates:
|
706
|
+
|
707
|
+
```html
|
708
|
+
<div class="mb-3">
|
709
|
+
<label class="form-label" for="user_skill_level">Skill level</label>
|
710
|
+
<div class="form-check">
|
711
|
+
<input class="form-check-input" id="user_skill_level_1" name="user[skill_level]" type="radio" value="1">
|
712
|
+
<label class="form-check-label" for="user_skill_level_1">Mind reading</label>
|
713
|
+
</div>
|
714
|
+
<div class="form-check">
|
715
|
+
<input class="form-check-input" id="user_skill_level_2" name="user[skill_level]" type="radio" value="2">
|
716
|
+
<label class="form-check-label" for="user_skill_level_2">Farming</label>
|
717
|
+
</div>
|
718
|
+
</div>
|
719
|
+
<input autocomplete="off" id="user_skills" multiple name="user[skills][]" type="hidden" value="">
|
720
|
+
<div class="mb-3">
|
721
|
+
<label class="form-label" for="user_skills">Skills</label>
|
722
|
+
<div class="form-check">
|
723
|
+
<input class="form-check-input" id="user_skills_1" name="user[skills][]" type="checkbox" value="1">
|
724
|
+
<label class="form-check-label" for="user_skills_1">Mind reading</label>
|
725
|
+
</div>
|
726
|
+
<div class="form-check">
|
727
|
+
<input class="form-check-input" id="user_skills_2" name="user[skills][]" type="checkbox" value="2">
|
728
|
+
<label class="form-check-label" for="user_skills_2">Farming</label>
|
729
|
+
</div>
|
730
|
+
</div>
|
731
|
+
```
|
732
|
+
|
416
733
|
NOTE: These helpers do not currently support a block, unlike their equivalent Rails helpers. See issue [#477](https://github.com/bootstrap-ruby/bootstrap_form/issues/477). If you need to use the block syntax, use `collection_check_boxes_without_bootstrap` or `collection_radio_buttons_without_bootstrap` for now.
|
417
734
|
|
418
735
|
Collection methods accept these options:
|
@@ -422,39 +739,98 @@ Collection methods accept these options:
|
|
422
739
|
* `:help`: Add a help span to the `form_group`
|
423
740
|
* Other options will be forwarded to the `radio_button`/`check_box` method
|
424
741
|
|
742
|
+
## Range Controls
|
743
|
+
|
744
|
+
You can create a range control like this:
|
745
|
+
|
746
|
+
![Example 24](demo/doc/screenshots/bootstrap/readme/24_example.png "Example 24")
|
747
|
+
```erb
|
748
|
+
<%= f.range_field :excellence %>
|
749
|
+
```
|
750
|
+
|
751
|
+
This generates:
|
752
|
+
|
753
|
+
```html
|
754
|
+
<div class="mb-3">
|
755
|
+
<label class="form-label" for="user_excellence">Excellence</label>
|
756
|
+
<input class="form-control" id="user_excellence" name="user[excellence]" type="range">
|
757
|
+
</div>
|
758
|
+
```
|
759
|
+
|
425
760
|
## Static Controls
|
426
761
|
|
427
762
|
You can create a static control like this:
|
428
763
|
|
764
|
+
![Example 25](demo/doc/screenshots/bootstrap/readme/25_example.png "Example 25")
|
429
765
|
```erb
|
430
766
|
<%= f.static_control :email %>
|
431
767
|
```
|
432
768
|
|
433
|
-
|
769
|
+
This generates:
|
434
770
|
|
435
771
|
```html
|
436
772
|
<div class="mb-3">
|
437
|
-
<label class="form-label
|
438
|
-
<
|
439
|
-
<input class="form-control-plaintext" id="user_email" name="user[email]" readonly="readonly" type="text" value="test@email.com"/>
|
440
|
-
</div>
|
773
|
+
<label class="form-label required" for="user_email">Email</label>
|
774
|
+
<input aria-required="true" class="form-control-plaintext" id="user_email" name="user[email]" readonly required="required" type="text" value="steve@example.com">
|
441
775
|
</div>
|
442
776
|
```
|
443
777
|
|
778
|
+
Here's the output for a horizontal layout:
|
779
|
+
|
780
|
+
![Example 26](demo/doc/screenshots/bootstrap/readme/26_example.png "Example 26")
|
781
|
+
```erb
|
782
|
+
<%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
|
783
|
+
<%= f.static_control :email %>
|
784
|
+
<% end %>
|
785
|
+
```
|
786
|
+
|
787
|
+
This generates:
|
788
|
+
|
789
|
+
```html
|
790
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
791
|
+
<div class="mb-3 row">
|
792
|
+
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
793
|
+
<div class="col-sm-10">
|
794
|
+
<input aria-required="true" class="form-control-plaintext" id="user_email" name="user[email]" readonly required="required" type="text" value="steve@example.com">
|
795
|
+
</div>
|
796
|
+
</div>
|
797
|
+
</form>
|
798
|
+
```
|
799
|
+
|
444
800
|
You can also create a static control that isn't based on a model attribute:
|
445
801
|
|
802
|
+
![Example 27](demo/doc/screenshots/bootstrap/readme/27_example.png "Example 27")
|
446
803
|
```erb
|
447
804
|
<%= f.static_control :field_name, label: "Custom Static Control", value: "Content Here" %>
|
448
805
|
```
|
449
806
|
|
807
|
+
This generates:
|
808
|
+
|
809
|
+
```html
|
810
|
+
<div class="mb-3">
|
811
|
+
<label class="form-label" for="user_field_name">Custom Static Control</label>
|
812
|
+
<input class="form-control-plaintext" id="user_field_name" name="user[field_name]" readonly type="text" value="Content Here">
|
813
|
+
</div>
|
814
|
+
```
|
815
|
+
|
450
816
|
`field_name` may be any name that isn't already used in the form. Note that you may get "unpermitted parameter" messages in your log file with this approach.
|
451
817
|
|
452
818
|
You can also create the static control the following way, if you don't need to get the value of the static control as a parameter when the form is submitted:
|
453
819
|
|
820
|
+
![Example 28](demo/doc/screenshots/bootstrap/readme/28_example.png "Example 28")
|
454
821
|
```erb
|
455
822
|
<%= f.static_control label: "Custom Static Control", value: "Content Here", name: nil %>
|
456
823
|
```
|
457
824
|
|
825
|
+
This generates:
|
826
|
+
|
827
|
+
```html
|
828
|
+
<div class="mb-3">
|
829
|
+
<label class="form-label" for="user_">Custom Static Control</label>
|
830
|
+
<input class="form-control-plaintext" id="user_" readonly type="text" value="Content Here">
|
831
|
+
</div>
|
832
|
+
```
|
833
|
+
|
458
834
|
(If you neither provide a field name nor `name: nil`, the Rails code that submits the form will give a JavaScript error.)
|
459
835
|
|
460
836
|
Prior to version 4 of `bootstrap_form`, you could pass a block to the `static_control` method.
|
@@ -475,28 +851,50 @@ this defining these selects as `inline-block` and a width of `auto`.
|
|
475
851
|
The `btn btn-secondary` CSS classes are automatically added to your submit
|
476
852
|
buttons.
|
477
853
|
|
854
|
+
![Example 29](demo/doc/screenshots/bootstrap/readme/29_example.png "Example 29")
|
478
855
|
```erb
|
479
856
|
<%= f.submit %>
|
480
857
|
```
|
481
858
|
|
859
|
+
This generates:
|
860
|
+
|
861
|
+
```html
|
862
|
+
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
863
|
+
```
|
864
|
+
|
482
865
|
You can also use the `primary` helper, which adds `btn btn-primary` to your
|
483
866
|
submit button:
|
484
867
|
|
868
|
+
![Example 30](demo/doc/screenshots/bootstrap/readme/30_example.png "Example 30")
|
485
869
|
```erb
|
486
870
|
<%= f.primary "Optional Label" %>
|
487
871
|
```
|
488
872
|
|
873
|
+
This generates:
|
874
|
+
|
875
|
+
```html
|
876
|
+
<input class="btn btn-primary" data-disable-with="Optional Label" name="commit" type="submit" value="Optional Label">
|
877
|
+
```
|
878
|
+
|
489
879
|
You can specify your own classes like this:
|
490
880
|
|
881
|
+
![Example 31](demo/doc/screenshots/bootstrap/readme/31_example.png "Example 31")
|
491
882
|
```erb
|
492
883
|
<%= f.submit "Log In", class: "btn btn-success" %>
|
493
884
|
```
|
494
885
|
|
886
|
+
This generates:
|
887
|
+
|
888
|
+
```html
|
889
|
+
<input class="btn btn-success" data-disable-with="Log In" name="commit" type="submit" value="Log In">
|
890
|
+
```
|
891
|
+
|
495
892
|
If the `primary` helper receives a `render_as_button: true` option or a block,
|
496
893
|
it will be rendered as an HTML button, instead of an input tag. This allows you
|
497
894
|
to specify HTML content and styling for your buttons (such as adding
|
498
895
|
illustrative icons to them). For example, the following statements
|
499
896
|
|
897
|
+
![Example 32](demo/doc/screenshots/bootstrap/readme/32_example.png "Example 32")
|
500
898
|
```erb
|
501
899
|
<%= f.primary "Save changes <span class='fa fa-save'></span>".html_safe, render_as_button: true %>
|
502
900
|
|
@@ -506,6 +904,17 @@ illustrative icons to them). For example, the following statements
|
|
506
904
|
end %>
|
507
905
|
```
|
508
906
|
|
907
|
+
This generates:
|
908
|
+
|
909
|
+
```html
|
910
|
+
<button class="btn btn-primary" name="button" type="submit">Save changes <span class="fa fa-save">
|
911
|
+
</span>
|
912
|
+
</button>
|
913
|
+
<button class="btn btn-primary" name="button" type="submit">Save changes <span class="fa fa-save">
|
914
|
+
</span>
|
915
|
+
</button>
|
916
|
+
```
|
917
|
+
|
509
918
|
are equivalent, and each of them both be rendered as:
|
510
919
|
|
511
920
|
```html
|
@@ -519,6 +928,7 @@ Bootstrap classes), or for element targeting via CSS classes.
|
|
519
928
|
Be aware, however, that using the `class` option will discard any extra classes
|
520
929
|
you add. As an example, the following button declarations
|
521
930
|
|
931
|
+
![Example 33](demo/doc/screenshots/bootstrap/readme/33_example.png "Example 33")
|
522
932
|
```erb
|
523
933
|
<%= f.primary "My Nice Button", extra_class: 'my-button' %>
|
524
934
|
|
@@ -528,9 +938,8 @@ you add. As an example, the following button declarations
|
|
528
938
|
will be rendered as
|
529
939
|
|
530
940
|
```html
|
531
|
-
<input
|
532
|
-
|
533
|
-
<input type="submit" value="My Button" class="my-button" />
|
941
|
+
<input class="btn btn-primary my-button" data-disable-with="My Nice Button" name="commit" type="submit" value="My Nice Button">
|
942
|
+
<input class="my-button" data-disable-with="My Button" name="commit" type="submit" value="My Button">
|
534
943
|
```
|
535
944
|
|
536
945
|
(some unimportant HTML attributes have been removed for simplicity)
|
@@ -539,6 +948,7 @@ will be rendered as
|
|
539
948
|
|
540
949
|
If you're using Rails 6, `bootstrap_form` supports the `rich_text_area` helper.
|
541
950
|
|
951
|
+
![Example 34](demo/doc/screenshots/bootstrap/readme/34_example.png "Example 34")
|
542
952
|
```erb
|
543
953
|
<%= f.rich_text_area(:life_story) %>
|
544
954
|
```
|
@@ -548,8 +958,47 @@ will be rendered as:
|
|
548
958
|
```html
|
549
959
|
<div class="mb-3">
|
550
960
|
<label class="form-label" for="user_life_story">Life story</label>
|
551
|
-
<input
|
552
|
-
<trix-
|
961
|
+
<input autocomplete="off" id="user_life_story_trix_input_user" name="user[life_story]" type="hidden">
|
962
|
+
<trix-toolbar id="trix-toolbar-1">
|
963
|
+
<div class="trix-button-row">
|
964
|
+
<span class="trix-button-group trix-button-group--text-tools" data-trix-button-group="text-tools">
|
965
|
+
<button class="trix-button trix-button--icon trix-button--icon-bold" data-trix-attribute="bold" data-trix-key="b" tabindex="-1" title="Bold" type="button">Bold</button>
|
966
|
+
<button class="trix-button trix-button--icon trix-button--icon-italic" data-trix-attribute="italic" data-trix-key="i" tabindex="-1" title="Italic" type="button">Italic</button>
|
967
|
+
<button class="trix-button trix-button--icon trix-button--icon-strike" data-trix-attribute="strike" tabindex="-1" title="Strikethrough" type="button">Strikethrough</button>
|
968
|
+
<button class="trix-button trix-button--icon trix-button--icon-link" data-trix-action="link" data-trix-attribute="href" data-trix-key="k" tabindex="-1" title="Link" type="button">Link</button>
|
969
|
+
</span>
|
970
|
+
<span class="trix-button-group trix-button-group--block-tools" data-trix-button-group="block-tools">
|
971
|
+
<button class="trix-button trix-button--icon trix-button--icon-heading-1" data-trix-attribute="heading1" tabindex="-1" title="Heading" type="button">Heading</button>
|
972
|
+
<button class="trix-button trix-button--icon trix-button--icon-quote" data-trix-attribute="quote" tabindex="-1" title="Quote" type="button">Quote</button>
|
973
|
+
<button class="trix-button trix-button--icon trix-button--icon-code" data-trix-attribute="code" tabindex="-1" title="Code" type="button">Code</button>
|
974
|
+
<button class="trix-button trix-button--icon trix-button--icon-bullet-list" data-trix-attribute="bullet" tabindex="-1" title="Bullets" type="button">Bullets</button>
|
975
|
+
<button class="trix-button trix-button--icon trix-button--icon-number-list" data-trix-attribute="number" tabindex="-1" title="Numbers" type="button">Numbers</button>
|
976
|
+
<button class="trix-button trix-button--icon trix-button--icon-decrease-nesting-level" data-trix-action="decreaseNestingLevel" tabindex="-1" title="Decrease Level" type="button">Decrease Level</button>
|
977
|
+
<button class="trix-button trix-button--icon trix-button--icon-increase-nesting-level" data-trix-action="increaseNestingLevel" tabindex="-1" title="Increase Level" type="button">Increase Level</button>
|
978
|
+
</span>
|
979
|
+
<span class="trix-button-group trix-button-group--file-tools" data-trix-button-group="file-tools">
|
980
|
+
<button class="trix-button trix-button--icon trix-button--icon-attach" data-trix-action="attachFiles" tabindex="-1" title="Attach Files" type="button">Attach Files</button>
|
981
|
+
</span>
|
982
|
+
<span class="trix-button-group-spacer">
|
983
|
+
</span>
|
984
|
+
<span class="trix-button-group trix-button-group--history-tools" data-trix-button-group="history-tools">
|
985
|
+
<button class="trix-button trix-button--icon trix-button--icon-undo" data-trix-action="undo" data-trix-key="z" tabindex="-1" title="Undo" type="button">Undo</button>
|
986
|
+
<button class="trix-button trix-button--icon trix-button--icon-redo" data-trix-action="redo" data-trix-key="shift+z" tabindex="-1" title="Redo" type="button">Redo</button>
|
987
|
+
</span>
|
988
|
+
</div>
|
989
|
+
<div class="trix-dialogs" data-trix-dialogs="">
|
990
|
+
<div class="trix-dialog trix-dialog--link" data-trix-dialog="href" data-trix-dialog-attribute="href">
|
991
|
+
<div class="trix-dialog__link-fields">
|
992
|
+
<input aria-label="URL" class="trix-input trix-input--dialog" data-trix-input="" disabled name="href" placeholder="Enter a URL…" required="" type="url">
|
993
|
+
<div class="trix-button-group">
|
994
|
+
<input class="trix-button trix-button--dialog" data-trix-method="setAttribute" type="button" value="Link">
|
995
|
+
<input class="trix-button trix-button--dialog" data-trix-method="removeAttribute" type="button" value="Unlink">
|
996
|
+
</div>
|
997
|
+
</div>
|
998
|
+
</div>
|
999
|
+
</div>
|
1000
|
+
</trix-toolbar>
|
1001
|
+
<trix-editor aria-label="Life story" class="trix-content form-control" contenteditable="" data-blob-url-template="http://test.host/rails/active_storage/blobs/redirect/:signed_id/:filename" data-direct-upload-url="http://test.host/rails/active_storage/direct_uploads" id="user_life_story" input="user_life_story_trix_input_user" role="textbox" toolbar="trix-toolbar-1" trix-id="1">
|
553
1002
|
</trix-editor>
|
554
1003
|
</div>
|
555
1004
|
```
|
@@ -567,10 +1016,17 @@ The `hidden_field` helper in `bootstrap_form` calls the Rails helper directly, a
|
|
567
1016
|
If you want to use the original Rails form helpers for a particular field,
|
568
1017
|
append `_without_bootstrap` to the helper:
|
569
1018
|
|
1019
|
+
![Example 35](demo/doc/screenshots/bootstrap/readme/35_example.png "Example 35")
|
570
1020
|
```erb
|
571
1021
|
<%= f.text_field_without_bootstrap :email %>
|
572
1022
|
```
|
573
1023
|
|
1024
|
+
This generates:
|
1025
|
+
|
1026
|
+
```html
|
1027
|
+
<input id="user_email" name="user[email]" type="text" value="steve@example.com">
|
1028
|
+
```
|
1029
|
+
|
574
1030
|
## Form Styles
|
575
1031
|
|
576
1032
|
By default, your forms will stack labels on top of controls and your controls
|
@@ -582,6 +1038,7 @@ To use an inline-layout form, use the `layout: :inline` option. To hide labels,
|
|
582
1038
|
use the `hide_label: true` option, which keeps your labels accessible to those
|
583
1039
|
using screen readers.
|
584
1040
|
|
1041
|
+
![Example 36](demo/doc/screenshots/bootstrap/readme/36_example.png "Example 36")
|
585
1042
|
```erb
|
586
1043
|
<%= bootstrap_form_for(@user, layout: :inline) do |f| %>
|
587
1044
|
<%= f.email_field :email, hide_label: true %>
|
@@ -591,12 +1048,44 @@ using screen readers.
|
|
591
1048
|
<% end %>
|
592
1049
|
```
|
593
1050
|
|
1051
|
+
This generates:
|
1052
|
+
|
1053
|
+
```html
|
1054
|
+
<form accept-charset="UTF-8" action="/users" class="new_user row row-cols-auto g-3 align-items-center" id="new_user" method="post">
|
1055
|
+
<div class="col">
|
1056
|
+
<label class="form-label visually-hidden mr-sm-2 required" for="user_email">Email</label>
|
1057
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1058
|
+
</div>
|
1059
|
+
<div class="col">
|
1060
|
+
<label class="form-label visually-hidden mr-sm-2" for="user_password">Password</label>
|
1061
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
1062
|
+
</div>
|
1063
|
+
<div class="form-check form-check-inline mb-3">
|
1064
|
+
<input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
|
1065
|
+
<input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
|
1066
|
+
<label class="form-check-label" for="user_remember_me">Remember me</label>
|
1067
|
+
</div>
|
1068
|
+
<div class="col">
|
1069
|
+
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
1070
|
+
</div>
|
1071
|
+
</form>
|
1072
|
+
```
|
1073
|
+
|
594
1074
|
To skip label rendering at all, use `skip_label: true` option.
|
595
1075
|
|
1076
|
+
![Example 37](demo/doc/screenshots/bootstrap/readme/37_example.png "Example 37")
|
596
1077
|
```erb
|
597
1078
|
<%= f.password_field :password, skip_label: true %>
|
598
1079
|
```
|
599
1080
|
|
1081
|
+
This generates:
|
1082
|
+
|
1083
|
+
```html
|
1084
|
+
<div class="mb-3">
|
1085
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
1086
|
+
</div>
|
1087
|
+
```
|
1088
|
+
|
600
1089
|
### Horizontal Forms
|
601
1090
|
|
602
1091
|
To use a horizontal-layout form with labels to the left of the control, use the
|
@@ -606,6 +1095,7 @@ To use a horizontal-layout form with labels to the left of the control, use the
|
|
606
1095
|
In the example below, the checkbox and submit button have been wrapped in a
|
607
1096
|
`form_group` to keep them properly aligned.
|
608
1097
|
|
1098
|
+
![Example 38](demo/doc/screenshots/bootstrap/readme/38_example.png "Example 38")
|
609
1099
|
```erb
|
610
1100
|
<%= bootstrap_form_for(@user, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10") do |f| %>
|
611
1101
|
<%= f.email_field :email %>
|
@@ -619,8 +1109,43 @@ In the example below, the checkbox and submit button have been wrapped in a
|
|
619
1109
|
<% end %>
|
620
1110
|
```
|
621
1111
|
|
1112
|
+
This generates:
|
1113
|
+
|
1114
|
+
```html
|
1115
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1116
|
+
<div class="mb-3 row">
|
1117
|
+
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1118
|
+
<div class="col-sm-10">
|
1119
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1120
|
+
</div>
|
1121
|
+
</div>
|
1122
|
+
<div class="mb-3 row">
|
1123
|
+
<label class="form-label col-form-label col-sm-2" for="user_password">Password</label>
|
1124
|
+
<div class="col-sm-10">
|
1125
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
1126
|
+
</div>
|
1127
|
+
</div>
|
1128
|
+
<div class="mb-3 row">
|
1129
|
+
<div class="col-sm-10 offset-sm-2">
|
1130
|
+
<div class="form-check">
|
1131
|
+
<input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
|
1132
|
+
<input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
|
1133
|
+
<label class="form-check-label" for="user_remember_me">Remember me</label>
|
1134
|
+
</div>
|
1135
|
+
</div>
|
1136
|
+
</div>
|
1137
|
+
|
1138
|
+
<div class="mb-3 row">
|
1139
|
+
<div class="col-sm-10 offset-sm-2">
|
1140
|
+
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
1141
|
+
</div>
|
1142
|
+
</div>
|
1143
|
+
</form>
|
1144
|
+
```
|
1145
|
+
|
622
1146
|
The `label_col` and `control_col` css classes can also be changed per control:
|
623
1147
|
|
1148
|
+
![Example 39](demo/doc/screenshots/bootstrap/readme/39_example.png "Example 39")
|
624
1149
|
```erb
|
625
1150
|
<%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
|
626
1151
|
<%= f.email_field :email %>
|
@@ -631,6 +1156,30 @@ The `label_col` and `control_col` css classes can also be changed per control:
|
|
631
1156
|
<% end %>
|
632
1157
|
```
|
633
1158
|
|
1159
|
+
This generates:
|
1160
|
+
|
1161
|
+
```html
|
1162
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1163
|
+
<div class="mb-3 row">
|
1164
|
+
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1165
|
+
<div class="col-sm-10">
|
1166
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1167
|
+
</div>
|
1168
|
+
</div>
|
1169
|
+
<div class="mb-3 row">
|
1170
|
+
<label class="form-label col-form-label col-sm-2" for="user_age">Age</label>
|
1171
|
+
<div class="col-sm-3">
|
1172
|
+
<input class="form-control" id="user_age" name="user[age]" type="text" value="42">
|
1173
|
+
</div>
|
1174
|
+
</div>
|
1175
|
+
<div class="mb-3 row">
|
1176
|
+
<div class="col-sm-10 offset-sm-2">
|
1177
|
+
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
1178
|
+
</div>
|
1179
|
+
</div>
|
1180
|
+
</form>
|
1181
|
+
```
|
1182
|
+
|
634
1183
|
or default value can be changed in initializer:
|
635
1184
|
|
636
1185
|
```ruby
|
@@ -653,6 +1202,7 @@ end
|
|
653
1202
|
|
654
1203
|
Control col wrapper class can be modified with `add_control_col_class`. This option will preserve column definition:
|
655
1204
|
|
1205
|
+
![Example 40](demo/doc/screenshots/bootstrap/readme/40_example.png "Example 40")
|
656
1206
|
```erb
|
657
1207
|
<%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
|
658
1208
|
<%= f.email_field :email %>
|
@@ -663,10 +1213,35 @@ Control col wrapper class can be modified with `add_control_col_class`. This opt
|
|
663
1213
|
<% end %>
|
664
1214
|
```
|
665
1215
|
|
1216
|
+
This generates:
|
1217
|
+
|
1218
|
+
```html
|
1219
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1220
|
+
<div class="mb-3 row">
|
1221
|
+
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1222
|
+
<div class="col-sm-10">
|
1223
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1224
|
+
</div>
|
1225
|
+
</div>
|
1226
|
+
<div class="mb-3 row">
|
1227
|
+
<label class="form-label col-form-label col-sm-2" for="user_age">Age</label>
|
1228
|
+
<div class="col-sm-10 additional-control-col-class">
|
1229
|
+
<input class="form-control" id="user_age" name="user[age]" type="text" value="42">
|
1230
|
+
</div>
|
1231
|
+
</div>
|
1232
|
+
<div class="mb-3 row">
|
1233
|
+
<div class="col-sm-10 offset-sm-2">
|
1234
|
+
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
1235
|
+
</div>
|
1236
|
+
</div>
|
1237
|
+
</form>
|
1238
|
+
```
|
1239
|
+
|
666
1240
|
### Custom Field Layout
|
667
1241
|
|
668
1242
|
The form-level `layout` can be overridden per field, unless the form-level layout was `inline`:
|
669
1243
|
|
1244
|
+
![Example 41](demo/doc/screenshots/bootstrap/readme/41_example.png "Example 41")
|
670
1245
|
```erb
|
671
1246
|
<%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
|
672
1247
|
<%= f.email_field :email %>
|
@@ -678,12 +1253,39 @@ The form-level `layout` can be overridden per field, unless the form-level layou
|
|
678
1253
|
<% end %>
|
679
1254
|
```
|
680
1255
|
|
1256
|
+
This generates:
|
1257
|
+
|
1258
|
+
```html
|
1259
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1260
|
+
<div class="mb-3 row">
|
1261
|
+
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1262
|
+
<div class="col-sm-10">
|
1263
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1264
|
+
</div>
|
1265
|
+
</div>
|
1266
|
+
<div class="mb-3">
|
1267
|
+
<label class="form-label" for="user_feet">Feet</label>
|
1268
|
+
<input class="form-control" id="user_feet" name="user[feet]" type="text" value="5">
|
1269
|
+
</div>
|
1270
|
+
<div class="mb-3">
|
1271
|
+
<label class="form-label" for="user_inches">Inches</label>
|
1272
|
+
<input class="form-control" id="user_inches" name="user[inches]" type="text" value="7">
|
1273
|
+
</div>
|
1274
|
+
<div class="mb-3 row">
|
1275
|
+
<div class="col-sm-10 offset-sm-2">
|
1276
|
+
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
1277
|
+
</div>
|
1278
|
+
</div>
|
1279
|
+
</form>
|
1280
|
+
```
|
1281
|
+
|
681
1282
|
A form-level `layout: :inline` can't be overridden because of the way Bootstrap 4 implements in-line layouts. One possible work-around is to leave the form-level layout as default, and specify the individual fields as `layout: :inline`, except for the fields(s) that should be other than in-line.
|
682
1283
|
|
683
1284
|
### Custom Form Element Styles
|
684
1285
|
|
685
1286
|
The `custom` option can be used to replace the browser default styles for check boxes and radio buttons with dedicated Bootstrap styled form elements. Here's an example:
|
686
1287
|
|
1288
|
+
![Example 42](demo/doc/screenshots/bootstrap/readme/42_example.png "Example 42")
|
687
1289
|
```erb
|
688
1290
|
<%= bootstrap_form_for(@user) do |f| %>
|
689
1291
|
<%= f.email_field :email %>
|
@@ -693,11 +1295,33 @@ The `custom` option can be used to replace the browser default styles for check
|
|
693
1295
|
<% end %>
|
694
1296
|
```
|
695
1297
|
|
1298
|
+
This generates:
|
1299
|
+
|
1300
|
+
```html
|
1301
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1302
|
+
<div class="mb-3">
|
1303
|
+
<label class="form-label required" for="user_email">Email</label>
|
1304
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1305
|
+
</div>
|
1306
|
+
<div class="mb-3">
|
1307
|
+
<label class="form-label" for="user_password">Password</label>
|
1308
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
1309
|
+
</div>
|
1310
|
+
<div class="form-check mb-3">
|
1311
|
+
<input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
|
1312
|
+
<input class="form-check-input" custom="true" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
|
1313
|
+
<label class="form-check-label" for="user_remember_me">Remember me</label>
|
1314
|
+
</div>
|
1315
|
+
<input class="btn btn-secondary" data-disable-with="Log In" name="commit" type="submit" value="Log In">
|
1316
|
+
</form>
|
1317
|
+
```
|
1318
|
+
|
696
1319
|
### Floating Labels
|
697
1320
|
|
698
1321
|
The `floating` option can be used to enable Bootstrap 5's floating labels. This option is supported on text fields
|
699
1322
|
and dropdowns. Here's an example:
|
700
1323
|
|
1324
|
+
![Example 43](demo/doc/screenshots/bootstrap/readme/43_example.png "Example 43")
|
701
1325
|
```erb
|
702
1326
|
<%= bootstrap_form_for(@user) do |f| %>
|
703
1327
|
<%= f.email_field :email, floating: true %>
|
@@ -708,6 +1332,34 @@ and dropdowns. Here's an example:
|
|
708
1332
|
<% end %>
|
709
1333
|
```
|
710
1334
|
|
1335
|
+
This generates:
|
1336
|
+
|
1337
|
+
```html
|
1338
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1339
|
+
<div class="mb-3 form-floating">
|
1340
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" placeholder="Email" required="required" type="email" value="steve@example.com">
|
1341
|
+
<label class="form-label required" for="user_email">Email</label>
|
1342
|
+
</div>
|
1343
|
+
<div class="mb-3 form-floating">
|
1344
|
+
<input class="form-control" id="user_password" name="user[password]" placeholder="Password" type="password">
|
1345
|
+
<label class="form-label" for="user_password">Password</label>
|
1346
|
+
</div>
|
1347
|
+
<div class="mb-3 form-floating">
|
1348
|
+
<input class="form-control" id="user_password" name="user[password]" placeholder="Password" type="password">
|
1349
|
+
<label class="form-label" for="user_password">Password</label>
|
1350
|
+
</div>
|
1351
|
+
<div class="mb-3 form-floating">
|
1352
|
+
<select class="form-select" id="user_status" name="user[status]">
|
1353
|
+
<option value="">Select a value</option>
|
1354
|
+
<option value="1">Active</option>
|
1355
|
+
<option value="2">Inactive</option>
|
1356
|
+
</select>
|
1357
|
+
<label class="form-label" for="user_status">Status</label>
|
1358
|
+
</div>
|
1359
|
+
<input class="btn btn-secondary" data-disable-with="Log In" name="commit" type="submit" value="Log In">
|
1360
|
+
</form>
|
1361
|
+
```
|
1362
|
+
|
711
1363
|
## Validation and Errors
|
712
1364
|
|
713
1365
|
Rails normally wraps fields with validation errors in a `div.field_with_errors`, but this behaviour isn't consistent with Bootstrap 4 styling. By default, `bootstrap_form` generations in-line errors which appear below the field. But it can also generate errors on the label, or not display any errors, leaving it up to you.
|
@@ -759,77 +1411,115 @@ To display an error message with an error summary, you can use the
|
|
759
1411
|
`alert_message` helper. This won't output anything unless a model validation
|
760
1412
|
has failed.
|
761
1413
|
|
1414
|
+
![Example 44](demo/doc/screenshots/bootstrap/readme/44_example.png "Example 44")
|
762
1415
|
```erb
|
763
|
-
<%=
|
1416
|
+
<%= bootstrap_form_for @user_with_error do |f| %>
|
1417
|
+
<%= f.alert_message "Please fix the errors below." %>
|
1418
|
+
<% end %>
|
764
1419
|
```
|
765
1420
|
|
766
1421
|
Which outputs:
|
767
1422
|
|
768
1423
|
```html
|
769
|
-
<
|
770
|
-
<
|
771
|
-
|
772
|
-
<
|
773
|
-
|
774
|
-
</
|
1424
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1425
|
+
<div class="alert alert-danger">
|
1426
|
+
<p>Please fix the errors below.</p>
|
1427
|
+
<ul class="rails-bootstrap-forms-error-summary">
|
1428
|
+
<li>Email is invalid</li>
|
1429
|
+
<li>Misc is invalid</li>
|
1430
|
+
</ul>
|
1431
|
+
</div>
|
1432
|
+
</form>
|
775
1433
|
```
|
776
1434
|
|
777
1435
|
You can turn off the error summary like this:
|
778
1436
|
|
1437
|
+
![Example 45](demo/doc/screenshots/bootstrap/readme/45_example.png "Example 45")
|
779
1438
|
```erb
|
780
|
-
<%=
|
1439
|
+
<%= bootstrap_form_for @user_with_error do |f| %>
|
1440
|
+
<%= f.alert_message "Please fix the errors below.", error_summary: false %>
|
1441
|
+
<% end %>
|
1442
|
+
```
|
1443
|
+
|
1444
|
+
This generates:
|
1445
|
+
|
1446
|
+
```html
|
1447
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1448
|
+
<div class="alert alert-danger">Please fix the errors below.</div>
|
1449
|
+
</form>
|
781
1450
|
```
|
782
1451
|
|
783
1452
|
To output a simple unordered list of errors, use the `error_summary` helper.
|
784
1453
|
|
1454
|
+
![Example 46](demo/doc/screenshots/bootstrap/readme/46_example.png "Example 46")
|
785
1455
|
```erb
|
786
|
-
<%= f
|
1456
|
+
<%= bootstrap_form_for @user_with_error do |f| %>
|
1457
|
+
<%= f.error_summary %>
|
1458
|
+
<% end %>
|
787
1459
|
```
|
788
1460
|
|
789
1461
|
Which outputs:
|
790
1462
|
|
791
1463
|
```html
|
792
|
-
<
|
793
|
-
<
|
794
|
-
</
|
1464
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1465
|
+
<ul class="rails-bootstrap-forms-error-summary">
|
1466
|
+
<li>Email is invalid</li>
|
1467
|
+
<li>Misc is invalid</li>
|
1468
|
+
</ul>
|
1469
|
+
</form>
|
795
1470
|
```
|
796
1471
|
|
797
1472
|
### Errors On
|
798
1473
|
|
799
1474
|
If you want to display a custom inline error for a specific attribute not represented by a form field, use the `errors_on` helper.
|
800
1475
|
|
1476
|
+
![Example 47](demo/doc/screenshots/bootstrap/readme/47_example.png "Example 47")
|
801
1477
|
```erb
|
802
|
-
<%= f
|
1478
|
+
<%= bootstrap_form_for @user_with_error do |f| %>
|
1479
|
+
<%= f.errors_on :email %>
|
1480
|
+
<% end %>
|
803
1481
|
```
|
804
1482
|
|
805
1483
|
Which outputs:
|
806
1484
|
|
807
1485
|
```html
|
808
|
-
<
|
1486
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1487
|
+
<div class="invalid-feedback">Email is invalid</div>
|
1488
|
+
</form>
|
809
1489
|
```
|
810
1490
|
|
811
1491
|
You can hide the attribute name like this:
|
812
1492
|
|
1493
|
+
![Example 48](demo/doc/screenshots/bootstrap/readme/48_example.png "Example 48")
|
813
1494
|
```erb
|
814
|
-
<%=
|
1495
|
+
<%= bootstrap_form_for @user_with_error do |f| %>
|
1496
|
+
<%= f.errors_on :email, hide_attribute_name: true %>
|
1497
|
+
<% end %>
|
815
1498
|
```
|
816
1499
|
|
817
1500
|
Which outputs:
|
818
1501
|
|
819
1502
|
```html
|
820
|
-
<
|
1503
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1504
|
+
<div class="invalid-feedback">is invalid</div>
|
1505
|
+
</form>
|
821
1506
|
```
|
822
1507
|
|
823
1508
|
You can also use a custom class for the wrapping div, like this:
|
824
1509
|
|
1510
|
+
![Example 49](demo/doc/screenshots/bootstrap/readme/49_example.png "Example 49")
|
825
1511
|
```erb
|
826
|
-
<%=
|
1512
|
+
<%= bootstrap_form_for @user_with_error do |f| %>
|
1513
|
+
<%= f.errors_on :email, custom_class: 'custom-error' %>
|
1514
|
+
<% end %>
|
827
1515
|
```
|
828
1516
|
|
829
1517
|
Which outputs:
|
830
1518
|
|
831
1519
|
```html
|
832
|
-
<
|
1520
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1521
|
+
<div class="custom-error">Email is invalid</div>
|
1522
|
+
</form>
|
833
1523
|
```
|
834
1524
|
|
835
1525
|
## Required Fields
|
@@ -852,11 +1542,72 @@ ActiveModel::Validations::PresenceValidator.
|
|
852
1542
|
|
853
1543
|
In cases where this behaviour is undesirable, use the `required` option to force the class to be present or absent:
|
854
1544
|
|
1545
|
+
![Example 50](demo/doc/screenshots/bootstrap/readme/50_example.png "Example 50")
|
855
1546
|
```erb
|
856
1547
|
<%= f.password_field :login, label: "New Username", required: true %>
|
857
1548
|
<%= f.password_field :password, label: "New Password", required: false %>
|
858
1549
|
```
|
859
1550
|
|
1551
|
+
This generates:
|
1552
|
+
|
1553
|
+
```html
|
1554
|
+
<div class="mb-3">
|
1555
|
+
<label class="form-label required" for="user_login">New Username</label>
|
1556
|
+
<input aria-required="true" class="form-control" id="user_login" name="user[login]" required="required" type="password">
|
1557
|
+
</div>
|
1558
|
+
<div class="mb-3">
|
1559
|
+
<label class="form-label" for="user_password">New Password</label>
|
1560
|
+
<input class="form-control" id="user_password" name="user[password]" type="password">
|
1561
|
+
</div>
|
1562
|
+
```
|
1563
|
+
|
1564
|
+
### Required belongs_to associations
|
1565
|
+
|
1566
|
+
Adding a form control for a `belongs_to` field will automatically pick up the associated presence validator.
|
1567
|
+
|
1568
|
+
![Example 51](demo/doc/screenshots/bootstrap/readme/51_example.png "Example 51")
|
1569
|
+
```erb
|
1570
|
+
<%= bootstrap_form_for(@address, url: '/address') do |f| %>
|
1571
|
+
<%= f.collection_select :user_id, @users, :id, :email, include_blank: "Select a value" %>
|
1572
|
+
<%= f.text_field :street %>
|
1573
|
+
<%= f.text_field :city %>
|
1574
|
+
<%= f.text_field :state %>
|
1575
|
+
<%= f.text_field :zip_code %>
|
1576
|
+
<%= f.submit "Save" %>
|
1577
|
+
<% end %>
|
1578
|
+
```
|
1579
|
+
|
1580
|
+
Generated HTML:
|
1581
|
+
|
1582
|
+
```html
|
1583
|
+
<form accept-charset="UTF-8" action="/address" class="new_address" id="new_address_1" method="post">
|
1584
|
+
<div class="mb-3">
|
1585
|
+
<label class="form-label required" for="address_user_id">User</label>
|
1586
|
+
<select class="form-select" id="address_user_id" name="address[user_id]">
|
1587
|
+
<option value="">Select a value</option>
|
1588
|
+
<option value="">steve@example.com</option>
|
1589
|
+
</select>
|
1590
|
+
</div>
|
1591
|
+
<div class="mb-3">
|
1592
|
+
<label class="form-label" for="address_street">Street</label>
|
1593
|
+
<input class="form-control" id="address_street" name="address[street]" type="text" value="Foo">
|
1594
|
+
</div>
|
1595
|
+
<div class="mb-3">
|
1596
|
+
<label class="form-label" for="address_city">City</label>
|
1597
|
+
<input class="form-control" id="address_city" name="address[city]" type="text">
|
1598
|
+
</div>
|
1599
|
+
<div class="mb-3">
|
1600
|
+
<label class="form-label" for="address_state">State</label>
|
1601
|
+
<input class="form-control" id="address_state" name="address[state]" type="text">
|
1602
|
+
</div>
|
1603
|
+
<div class="mb-3">
|
1604
|
+
<label class="form-label" for="address_zip_code">Zip code</label>
|
1605
|
+
<input class="form-control" id="address_zip_code" name="address[zip_code]" type="text">
|
1606
|
+
</div>
|
1607
|
+
<input class="btn btn-secondary" data-disable-with="Save" name="commit" type="submit" value="Save">
|
1608
|
+
</form>
|
1609
|
+
```
|
1610
|
+
|
860
1611
|
## Internationalization
|
861
1612
|
|
862
1613
|
bootstrap_form follows standard rails conventions so it's i18n-ready. See more
|