bootstrap_form 5.1.0 → 5.2.1
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 +21 -8
- data/.gitignore +4 -2
- data/.rubocop.yml +2 -1
- data/.yarnrc +5 -0
- data/CHANGELOG.md +13 -3
- data/CONTRIBUTING.md +101 -14
- data/Dangerfile +4 -4
- data/Dockerfile +5 -5
- data/Gemfile +5 -21
- data/README.md +108 -42
- data/RELEASING.md +12 -1
- data/Rakefile +7 -6
- data/bootstrap_form.gemspec +6 -8
- data/docker-compose.yml +6 -24
- data/gemfiles/6.0.gemfile +1 -1
- data/gemfiles/6.1.gemfile +1 -1
- data/gemfiles/7.0.gemfile +2 -3
- data/gemfiles/common.gemfile +28 -0
- data/gemfiles/edge.gemfile +3 -2
- data/lib/bootstrap_form/components/labels.rb +3 -9
- data/lib/bootstrap_form/components/validation.rb +36 -19
- data/lib/bootstrap_form/form_builder.rb +4 -1
- data/lib/bootstrap_form/form_group.rb +9 -6
- data/lib/bootstrap_form/form_group_builder.rb +10 -7
- data/lib/bootstrap_form/helpers/bootstrap.rb +7 -8
- data/lib/bootstrap_form/helpers/field.rb +26 -0
- data/lib/bootstrap_form/helpers.rb +1 -0
- data/lib/bootstrap_form/inputs/base.rb +2 -2
- data/lib/bootstrap_form/inputs/check_box.rb +22 -6
- data/lib/bootstrap_form/inputs/radio_button.rb +3 -3
- data/lib/bootstrap_form/inputs/range_field.rb +1 -1
- data/lib/bootstrap_form/inputs.rb +1 -1
- data/lib/bootstrap_form/version.rb +2 -1
- data/lib/bootstrap_form.rb +1 -1
- metadata +14 -146
- data/demo/.postcssrc.yml +0 -3
- data/demo/.ruby-version +0 -1
- data/demo/Gemfile +0 -80
- data/demo/Gemfile.lock +0 -261
- data/demo/Procfile.dev +0 -2
- data/demo/README.md +0 -17
- data/demo/Rakefile +0 -6
- data/demo/app/assets/builds/.keep +0 -0
- data/demo/app/assets/builds/application.js.LICENSE.txt +0 -9
- data/demo/app/assets/config/manifest.js +0 -2
- data/demo/app/assets/stylesheets/actiontext.css +0 -31
- 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 -29
- data/demo/app/controllers/users_controller.rb +0 -9
- data/demo/app/helpers/bootstrap_helper.rb +0 -27
- data/demo/app/javascript/application.js +0 -3
- 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/skill.rb +0 -15
- data/demo/app/models/super_user.rb +0 -2
- data/demo/app/models/user.rb +0 -25
- 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/action_text/contents/_content.html.erb +0 -3
- data/demo/app/views/layouts/application.html.erb +0 -76
- data/demo/bin/bundle +0 -3
- data/demo/bin/dev +0 -9
- 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/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 -6
- 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 -84
- data/demo/doc/screenshots/bootstrap/index/00_horizontal_form.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/01_with_validation_error.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/02_inline_form.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/03_simple_action_text_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/04_floating_labels.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/00_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/01_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/02_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/03_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/04_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/05_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/06_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/07_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/08_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/09_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/10_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/11_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/12_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/13_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/14_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/15_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/16_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/17_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/18_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/19_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/20_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/21_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/22_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/23_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/24_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/25_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/26_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/27_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/28_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/29_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/30_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/31_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/32_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/33_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/34_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/35_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/36_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/37_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/38_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/39_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/40_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/41_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/42_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/43_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/44_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/45_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/46_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/47_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/48_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/49_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/50_example.png +0 -0
- data/demo/log/.keep +0 -0
- data/demo/package.json +0 -21
- data/demo/public/favicon.ico +0 -0
- data/demo/test/application_system_test_case.rb +0 -8
- data/demo/test/controllers/bootstrap_controller_test.rb +0 -8
- data/demo/test/controllers/users_controller_test.rb +0 -13
- data/demo/test/fixtures/action_text/rich_texts.yml +0 -4
- data/demo/test/fixtures/users.yml +0 -2
- data/demo/test/system/bootstrap_test.rb +0 -84
- data/demo/test/test_helper.rb +0 -10
- data/demo/webpack.config.js +0 -20
- data/demo/yarn.lock +0 -7176
- data/gemfiles/5.2.gemfile +0 -4
data/README.md
CHANGED
@@ -25,8 +25,8 @@ 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
|
@@ -42,7 +42,7 @@ And follow the remaining instructions in the [official bootstrap installation gu
|
|
42
42
|
Add the `bootstrap_form` gem to your `Gemfile`:
|
43
43
|
|
44
44
|
```ruby
|
45
|
-
gem "bootstrap_form", "~> 5.
|
45
|
+
gem "bootstrap_form", "~> 5.2"
|
46
46
|
```
|
47
47
|
|
48
48
|
Then:
|
@@ -84,7 +84,7 @@ This generates the following HTML:
|
|
84
84
|
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
85
85
|
<div class="mb-3">
|
86
86
|
<label class="form-label required" for="user_email">Email</label>
|
87
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
87
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
88
88
|
</div>
|
89
89
|
<div class="mb-3">
|
90
90
|
<label class="form-label" for="user_password">Password</label>
|
@@ -125,8 +125,6 @@ This generates:
|
|
125
125
|
|
126
126
|
### bootstrap_form_with
|
127
127
|
|
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.
|
129
|
-
|
130
128
|
To get started, just use the `bootstrap_form_with` helper in place of `form_with`. Here's an example:
|
131
129
|
|
132
130
|
![Example 2](demo/doc/screenshots/bootstrap/readme/02_example.png "Example 2")
|
@@ -145,7 +143,7 @@ This generates:
|
|
145
143
|
<form accept-charset="UTF-8" action="/users" method="post">
|
146
144
|
<div class="mb-3">
|
147
145
|
<label class="form-label required" for="user_email">Email</label>
|
148
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
146
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
149
147
|
</div>
|
150
148
|
<div class="mb-3">
|
151
149
|
<label class="form-label" for="user_password">Password</label>
|
@@ -200,7 +198,7 @@ date_field password_field time_field
|
|
200
198
|
date_select phone_field time_select
|
201
199
|
datetime_field radio_button time_zone_select
|
202
200
|
datetime_local_field range_field url_field
|
203
|
-
datetime_select rich_text_area
|
201
|
+
datetime_select rich_text_area week_field
|
204
202
|
```
|
205
203
|
|
206
204
|
By default, the helpers generate a `label` tag, and an `input`, `select`, or `textarea` tag, by calling the Rails `label` helper, and then the Rails helper with the same name as the `bootstrap_form` helper.
|
@@ -278,7 +276,7 @@ This generates:
|
|
278
276
|
```html
|
279
277
|
<div class="mb-3">
|
280
278
|
<label class="form-label custom-class required" for="user_email">Email</label>
|
281
|
-
<input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com">
|
279
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="text" value="steve@example.com">
|
282
280
|
</div>
|
283
281
|
```
|
284
282
|
|
@@ -294,7 +292,7 @@ This generates:
|
|
294
292
|
```html
|
295
293
|
<div class="mb-3">
|
296
294
|
<label class="form-label visually-hidden required" for="user_email">Email</label>
|
297
|
-
<input class="form-control" id="user_email" name="user[email]" placeholder="Email" type="text" value="steve@example.com">
|
295
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" placeholder="Email" required="required" type="text" value="steve@example.com">
|
298
296
|
</div>
|
299
297
|
```
|
300
298
|
|
@@ -312,7 +310,7 @@ This generates:
|
|
312
310
|
```html
|
313
311
|
<div class="mb-3">
|
314
312
|
<label class="form-label required" for="user_email">Email</label>
|
315
|
-
<input class="custom-class" id="user_email" name="user[email]" type="text" value="steve@example.com">
|
313
|
+
<input aria-required="true" class="custom-class" id="user_email" name="user[email]" required="required" type="text" value="steve@example.com">
|
316
314
|
</div>
|
317
315
|
```
|
318
316
|
|
@@ -438,7 +436,7 @@ This generates:
|
|
438
436
|
<div class="mb-3">
|
439
437
|
<label class="form-label required" for="user_email">Email</label>
|
440
438
|
<div class="input-group input-group-lg">
|
441
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
439
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
442
440
|
<input class="btn btn-primary" data-disable-with="Subscribe" name="commit" type="submit" value="Subscribe">
|
443
441
|
</div>
|
444
442
|
</div>
|
@@ -503,7 +501,7 @@ Generated HTML:
|
|
503
501
|
|
504
502
|
```html
|
505
503
|
<div class="mb-3">
|
506
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
504
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
507
505
|
</div>
|
508
506
|
```
|
509
507
|
|
@@ -753,7 +751,7 @@ This generates:
|
|
753
751
|
```html
|
754
752
|
<div class="mb-3">
|
755
753
|
<label class="form-label" for="user_excellence">Excellence</label>
|
756
|
-
<input class="form-
|
754
|
+
<input class="form-range" id="user_excellence" name="user[excellence]" type="range">
|
757
755
|
</div>
|
758
756
|
```
|
759
757
|
|
@@ -771,7 +769,7 @@ This generates:
|
|
771
769
|
```html
|
772
770
|
<div class="mb-3">
|
773
771
|
<label class="form-label required" for="user_email">Email</label>
|
774
|
-
<input class="form-control-plaintext" id="user_email" name="user[email]" readonly type="text" value="steve@example.com">
|
772
|
+
<input aria-required="true" class="form-control-plaintext" id="user_email" name="user[email]" readonly required="required" type="text" value="steve@example.com">
|
775
773
|
</div>
|
776
774
|
```
|
777
775
|
|
@@ -791,7 +789,7 @@ This generates:
|
|
791
789
|
<div class="mb-3 row">
|
792
790
|
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
793
791
|
<div class="col-sm-10">
|
794
|
-
<input class="form-control-plaintext" id="user_email" name="user[email]" readonly type="text" value="steve@example.com">
|
792
|
+
<input aria-required="true" class="form-control-plaintext" id="user_email" name="user[email]" readonly required="required" type="text" value="steve@example.com">
|
795
793
|
</div>
|
796
794
|
</div>
|
797
795
|
</form>
|
@@ -946,8 +944,6 @@ will be rendered as
|
|
946
944
|
|
947
945
|
## Rich Text Areas AKA Trix Editor
|
948
946
|
|
949
|
-
If you're using Rails 6, `bootstrap_form` supports the `rich_text_area` helper.
|
950
|
-
|
951
947
|
![Example 34](demo/doc/screenshots/bootstrap/readme/34_example.png "Example 34")
|
952
948
|
```erb
|
953
949
|
<%= f.rich_text_area(:life_story) %>
|
@@ -1054,7 +1050,7 @@ This generates:
|
|
1054
1050
|
<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
1051
|
<div class="col">
|
1056
1052
|
<label class="form-label visually-hidden mr-sm-2 required" for="user_email">Email</label>
|
1057
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
1053
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1058
1054
|
</div>
|
1059
1055
|
<div class="col">
|
1060
1056
|
<label class="form-label visually-hidden mr-sm-2" for="user_password">Password</label>
|
@@ -1116,7 +1112,7 @@ This generates:
|
|
1116
1112
|
<div class="mb-3 row">
|
1117
1113
|
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1118
1114
|
<div class="col-sm-10">
|
1119
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
1115
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1120
1116
|
</div>
|
1121
1117
|
</div>
|
1122
1118
|
<div class="mb-3 row">
|
@@ -1134,7 +1130,7 @@ This generates:
|
|
1134
1130
|
</div>
|
1135
1131
|
</div>
|
1136
1132
|
</div>
|
1137
|
-
|
1133
|
+
|
1138
1134
|
<div class="mb-3 row">
|
1139
1135
|
<div class="col-sm-10 offset-sm-2">
|
1140
1136
|
<input class="btn btn-secondary" data-disable-with="Create User" name="commit" type="submit" value="Create User">
|
@@ -1163,7 +1159,7 @@ This generates:
|
|
1163
1159
|
<div class="mb-3 row">
|
1164
1160
|
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1165
1161
|
<div class="col-sm-10">
|
1166
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
1162
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1167
1163
|
</div>
|
1168
1164
|
</div>
|
1169
1165
|
<div class="mb-3 row">
|
@@ -1220,7 +1216,7 @@ This generates:
|
|
1220
1216
|
<div class="mb-3 row">
|
1221
1217
|
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1222
1218
|
<div class="col-sm-10">
|
1223
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
1219
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1224
1220
|
</div>
|
1225
1221
|
</div>
|
1226
1222
|
<div class="mb-3 row">
|
@@ -1260,7 +1256,7 @@ This generates:
|
|
1260
1256
|
<div class="mb-3 row">
|
1261
1257
|
<label class="form-label col-form-label col-sm-2 required" for="user_email">Email</label>
|
1262
1258
|
<div class="col-sm-10">
|
1263
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
1259
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1264
1260
|
</div>
|
1265
1261
|
</div>
|
1266
1262
|
<div class="mb-3">
|
@@ -1301,7 +1297,7 @@ This generates:
|
|
1301
1297
|
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1302
1298
|
<div class="mb-3">
|
1303
1299
|
<label class="form-label required" for="user_email">Email</label>
|
1304
|
-
<input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com">
|
1300
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" required="required" type="email" value="steve@example.com">
|
1305
1301
|
</div>
|
1306
1302
|
<div class="mb-3">
|
1307
1303
|
<label class="form-label" for="user_password">Password</label>
|
@@ -1337,7 +1333,7 @@ This generates:
|
|
1337
1333
|
```html
|
1338
1334
|
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1339
1335
|
<div class="mb-3 form-floating">
|
1340
|
-
<input class="form-control" id="user_email" name="user[email]" placeholder="Email" type="email" value="steve@example.com">
|
1336
|
+
<input aria-required="true" class="form-control" id="user_email" name="user[email]" placeholder="Email" required="required" type="email" value="steve@example.com">
|
1341
1337
|
<label class="form-label required" for="user_email">Email</label>
|
1342
1338
|
</div>
|
1343
1339
|
<div class="mb-3 form-floating">
|
@@ -1369,18 +1365,29 @@ Rails normally wraps fields with validation errors in a `div.field_with_errors`,
|
|
1369
1365
|
By default, fields that have validation errors will be outlined in red and the
|
1370
1366
|
error will be displayed below the field. Here's an example:
|
1371
1367
|
|
1368
|
+
![Example 44](demo/doc/screenshots/bootstrap/readme/44_example.png "Example 44")
|
1369
|
+
```erb
|
1370
|
+
<%= bootstrap_form_for(@user_with_error) do |f| %>
|
1371
|
+
<%= f.email_field :email %>
|
1372
|
+
<% end %>
|
1373
|
+
```
|
1374
|
+
|
1375
|
+
Generated HTML:
|
1376
|
+
|
1372
1377
|
```html
|
1373
|
-
<
|
1374
|
-
<
|
1375
|
-
|
1376
|
-
|
1377
|
-
</div>
|
1378
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1379
|
+
<div class="mb-3">
|
1380
|
+
<label class="form-label required" for="user_email">Email</label>
|
1381
|
+
<input aria-required="true" class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
|
1382
|
+
<div class="invalid-feedback">is invalid</div>
|
1383
|
+
</div>
|
1384
|
+
</form>
|
1378
1385
|
```
|
1379
1386
|
|
1380
1387
|
You can turn off inline errors for the entire form like this:
|
1381
1388
|
|
1382
1389
|
```erb
|
1383
|
-
<%= bootstrap_form_for(@
|
1390
|
+
<%= bootstrap_form_for(@user_with_error, inline_errors: false) do |f| %>
|
1384
1391
|
...
|
1385
1392
|
<% end %>
|
1386
1393
|
```
|
@@ -1390,12 +1397,24 @@ You can turn off inline errors for the entire form like this:
|
|
1390
1397
|
You can also display validation errors in the field's label; just turn
|
1391
1398
|
on the `:label_errors` option. Here's an example:
|
1392
1399
|
|
1400
|
+
![Example 45](demo/doc/screenshots/bootstrap/readme/45_example.png "Example 45")
|
1393
1401
|
```erb
|
1394
|
-
<%= bootstrap_form_for(@
|
1395
|
-
|
1402
|
+
<%= bootstrap_form_for(@user_with_error, label_errors: true) do |f| %>
|
1403
|
+
<%= f.email_field :email %>
|
1396
1404
|
<% end %>
|
1397
1405
|
```
|
1398
1406
|
|
1407
|
+
Generated HTML:
|
1408
|
+
|
1409
|
+
```html
|
1410
|
+
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
|
1411
|
+
<div class="mb-3">
|
1412
|
+
<label class="form-label required text-danger" for="user_email">Email is invalid</label>
|
1413
|
+
<input aria-required="true" class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
|
1414
|
+
</div>
|
1415
|
+
</form>
|
1416
|
+
```
|
1417
|
+
|
1399
1418
|
By default, turning on `:label_errors` will also turn off
|
1400
1419
|
`:inline_errors`. If you want both turned on, you can do that too:
|
1401
1420
|
|
@@ -1411,7 +1430,7 @@ To display an error message with an error summary, you can use the
|
|
1411
1430
|
`alert_message` helper. This won't output anything unless a model validation
|
1412
1431
|
has failed.
|
1413
1432
|
|
1414
|
-
![Example
|
1433
|
+
![Example 46](demo/doc/screenshots/bootstrap/readme/46_example.png "Example 46")
|
1415
1434
|
```erb
|
1416
1435
|
<%= bootstrap_form_for @user_with_error do |f| %>
|
1417
1436
|
<%= f.alert_message "Please fix the errors below." %>
|
@@ -1434,7 +1453,7 @@ Which outputs:
|
|
1434
1453
|
|
1435
1454
|
You can turn off the error summary like this:
|
1436
1455
|
|
1437
|
-
![Example
|
1456
|
+
![Example 47](demo/doc/screenshots/bootstrap/readme/47_example.png "Example 47")
|
1438
1457
|
```erb
|
1439
1458
|
<%= bootstrap_form_for @user_with_error do |f| %>
|
1440
1459
|
<%= f.alert_message "Please fix the errors below.", error_summary: false %>
|
@@ -1451,7 +1470,7 @@ This generates:
|
|
1451
1470
|
|
1452
1471
|
To output a simple unordered list of errors, use the `error_summary` helper.
|
1453
1472
|
|
1454
|
-
![Example
|
1473
|
+
![Example 48](demo/doc/screenshots/bootstrap/readme/48_example.png "Example 48")
|
1455
1474
|
```erb
|
1456
1475
|
<%= bootstrap_form_for @user_with_error do |f| %>
|
1457
1476
|
<%= f.error_summary %>
|
@@ -1473,7 +1492,7 @@ Which outputs:
|
|
1473
1492
|
|
1474
1493
|
If you want to display a custom inline error for a specific attribute not represented by a form field, use the `errors_on` helper.
|
1475
1494
|
|
1476
|
-
![Example
|
1495
|
+
![Example 49](demo/doc/screenshots/bootstrap/readme/49_example.png "Example 49")
|
1477
1496
|
```erb
|
1478
1497
|
<%= bootstrap_form_for @user_with_error do |f| %>
|
1479
1498
|
<%= f.errors_on :email %>
|
@@ -1490,7 +1509,7 @@ Which outputs:
|
|
1490
1509
|
|
1491
1510
|
You can hide the attribute name like this:
|
1492
1511
|
|
1493
|
-
![Example
|
1512
|
+
![Example 50](demo/doc/screenshots/bootstrap/readme/50_example.png "Example 50")
|
1494
1513
|
```erb
|
1495
1514
|
<%= bootstrap_form_for @user_with_error do |f| %>
|
1496
1515
|
<%= f.errors_on :email, hide_attribute_name: true %>
|
@@ -1507,7 +1526,7 @@ Which outputs:
|
|
1507
1526
|
|
1508
1527
|
You can also use a custom class for the wrapping div, like this:
|
1509
1528
|
|
1510
|
-
![Example
|
1529
|
+
![Example 51](demo/doc/screenshots/bootstrap/readme/51_example.png "Example 51")
|
1511
1530
|
```erb
|
1512
1531
|
<%= bootstrap_form_for @user_with_error do |f| %>
|
1513
1532
|
<%= f.errors_on :email, custom_class: 'custom-error' %>
|
@@ -1542,7 +1561,7 @@ ActiveModel::Validations::PresenceValidator.
|
|
1542
1561
|
|
1543
1562
|
In cases where this behaviour is undesirable, use the `required` option to force the class to be present or absent:
|
1544
1563
|
|
1545
|
-
![Example
|
1564
|
+
![Example 52](demo/doc/screenshots/bootstrap/readme/52_example.png "Example 52")
|
1546
1565
|
```erb
|
1547
1566
|
<%= f.password_field :login, label: "New Username", required: true %>
|
1548
1567
|
<%= f.password_field :password, label: "New Password", required: false %>
|
@@ -1553,7 +1572,7 @@ This generates:
|
|
1553
1572
|
```html
|
1554
1573
|
<div class="mb-3">
|
1555
1574
|
<label class="form-label required" for="user_login">New Username</label>
|
1556
|
-
<input class="form-control" id="user_login" name="user[login]" required="required" type="password">
|
1575
|
+
<input aria-required="true" class="form-control" id="user_login" name="user[login]" required="required" type="password">
|
1557
1576
|
</div>
|
1558
1577
|
<div class="mb-3">
|
1559
1578
|
<label class="form-label" for="user_password">New Password</label>
|
@@ -1561,6 +1580,53 @@ This generates:
|
|
1561
1580
|
</div>
|
1562
1581
|
```
|
1563
1582
|
|
1583
|
+
### Required belongs_to associations
|
1584
|
+
|
1585
|
+
Adding a form control for a `belongs_to` field will automatically pick up the associated presence validator.
|
1586
|
+
|
1587
|
+
![Example 53](demo/doc/screenshots/bootstrap/readme/53_example.png "Example 53")
|
1588
|
+
```erb
|
1589
|
+
<%= bootstrap_form_for(@address, url: '/address') do |f| %>
|
1590
|
+
<%= f.collection_select :user_id, @users, :id, :email, include_blank: "Select a value" %>
|
1591
|
+
<%= f.text_field :street %>
|
1592
|
+
<%= f.text_field :city %>
|
1593
|
+
<%= f.text_field :state %>
|
1594
|
+
<%= f.text_field :zip_code %>
|
1595
|
+
<%= f.submit "Save" %>
|
1596
|
+
<% end %>
|
1597
|
+
```
|
1598
|
+
|
1599
|
+
Generated HTML:
|
1600
|
+
|
1601
|
+
```html
|
1602
|
+
<form accept-charset="UTF-8" action="/address" class="new_address" id="new_address_1" method="post">
|
1603
|
+
<div class="mb-3">
|
1604
|
+
<label class="form-label required" for="address_user_id">User</label>
|
1605
|
+
<select class="form-select" id="address_user_id" name="address[user_id]">
|
1606
|
+
<option value="">Select a value</option>
|
1607
|
+
<option value="">steve@example.com</option>
|
1608
|
+
</select>
|
1609
|
+
</div>
|
1610
|
+
<div class="mb-3">
|
1611
|
+
<label class="form-label" for="address_street">Street</label>
|
1612
|
+
<input class="form-control" id="address_street" name="address[street]" type="text" value="Foo">
|
1613
|
+
</div>
|
1614
|
+
<div class="mb-3">
|
1615
|
+
<label class="form-label" for="address_city">City</label>
|
1616
|
+
<input class="form-control" id="address_city" name="address[city]" type="text">
|
1617
|
+
</div>
|
1618
|
+
<div class="mb-3">
|
1619
|
+
<label class="form-label" for="address_state">State</label>
|
1620
|
+
<input class="form-control" id="address_state" name="address[state]" type="text">
|
1621
|
+
</div>
|
1622
|
+
<div class="mb-3">
|
1623
|
+
<label class="form-label" for="address_zip_code">Zip code</label>
|
1624
|
+
<input class="form-control" id="address_zip_code" name="address[zip_code]" type="text">
|
1625
|
+
</div>
|
1626
|
+
<input class="btn btn-secondary" data-disable-with="Save" name="commit" type="submit" value="Save">
|
1627
|
+
</form>
|
1628
|
+
```
|
1629
|
+
|
1564
1630
|
## Internationalization
|
1565
1631
|
|
1566
1632
|
bootstrap_form follows standard rails conventions so it's i18n-ready. See more
|
data/RELEASING.md
CHANGED
@@ -11,7 +11,18 @@ Follow these steps to release a new version of bootstrap_form to rubygems.org.
|
|
11
11
|
## How to release
|
12
12
|
|
13
13
|
1. Run `BUNDLE_GEMFILE=gemfiles/7.0.gemfile bundle update` to make sure that you have all the gems necessary for testing and releasing.
|
14
|
-
2. **Ensure the tests are passing by running
|
14
|
+
2. **Ensure the tests are passing by running the tests**
|
15
|
+
|
16
|
+
(There should be no errors or warnings.)
|
17
|
+
|
18
|
+
BUNDLE_GEMFILE=gemfiles/7.0.gemfile bundle exec rake test
|
19
|
+
|
20
|
+
2. **Ensure the demo tests are passing by running**
|
21
|
+
|
22
|
+
cd demo
|
23
|
+
bundle update
|
24
|
+
bundle exec rake test:all
|
25
|
+
|
15
26
|
3. Determine which would be the correct next version number according to [semver](http://semver.org/).
|
16
27
|
4. Update the version in `./lib/bootstrap_form/version.rb`.
|
17
28
|
5. Update the GitHub diff links at the beginning of `CHANGELOG.md` (The pattern should be obvious when you look at them).
|
data/Rakefile
CHANGED
@@ -17,12 +17,13 @@ end
|
|
17
17
|
|
18
18
|
require 'bundler/gem_tasks'
|
19
19
|
|
20
|
-
require
|
20
|
+
require "minitest/test_task"
|
21
21
|
|
22
|
-
|
23
|
-
t.libs <<
|
24
|
-
t.
|
25
|
-
t.
|
22
|
+
Minitest::TestTask.create(:test) do |t|
|
23
|
+
t.libs << "test"
|
24
|
+
t.libs << "lib"
|
25
|
+
t.warning = false
|
26
|
+
t.test_globs = ["test/**/*_test.rb"]
|
26
27
|
end
|
27
28
|
|
28
29
|
# This automatically updates GitHub Releases whenever we `rake release` the gem
|
@@ -34,4 +35,4 @@ end
|
|
34
35
|
desc 'Run RuboCop checks'
|
35
36
|
RuboCop::RakeTask.new(:rubocop)
|
36
37
|
|
37
|
-
task default: %i[test rubocop]
|
38
|
+
task default: %i[test rubocop:autocorrect]
|
data/bootstrap_form.gemspec
CHANGED
@@ -3,30 +3,28 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
3
|
|
4
4
|
require "bootstrap_form/version"
|
5
5
|
|
6
|
-
REQUIRED_RAILS_VERSION = ">= 5.2".freeze
|
7
|
-
|
8
6
|
Gem::Specification.new do |s|
|
9
7
|
s.name = "bootstrap_form"
|
10
8
|
s.version = BootstrapForm::VERSION
|
11
9
|
s.authors = ["Stephen Potenza", "Carlos Lopes"]
|
12
10
|
s.email = ["potenza@gmail.com", "carlos.el.lopes@gmail.com"]
|
13
11
|
s.homepage = "https://github.com/bootstrap-ruby/bootstrap_form"
|
14
|
-
s.summary = "Rails form builder that makes it easy to style forms using "\
|
12
|
+
s.summary = "Rails form builder that makes it easy to style forms using " \
|
15
13
|
"Bootstrap 5"
|
16
|
-
s.description = "bootstrap_form is a rails form builder that makes it super "\
|
14
|
+
s.description = "bootstrap_form is a rails form builder that makes it super " \
|
17
15
|
"easy to create beautiful-looking forms using Bootstrap 5"
|
18
16
|
s.license = "MIT"
|
19
17
|
s.metadata = { "rubygems_mfa_required" => "true" }
|
20
18
|
|
21
19
|
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
22
|
-
f.match(%r{^(test)/})
|
20
|
+
f.match(%r{^(test)/|^(demo)/})
|
23
21
|
end
|
24
22
|
|
25
23
|
s.bindir = "exe"
|
26
24
|
s.require_paths = ["lib"]
|
27
25
|
|
28
|
-
s.required_ruby_version = ">=
|
26
|
+
s.required_ruby_version = ">= 3.0"
|
29
27
|
|
30
|
-
s.add_dependency("actionpack", REQUIRED_RAILS_VERSION)
|
31
|
-
s.add_dependency("activemodel", REQUIRED_RAILS_VERSION)
|
28
|
+
s.add_dependency("actionpack", BootstrapForm::REQUIRED_RAILS_VERSION)
|
29
|
+
s.add_dependency("activemodel", BootstrapForm::REQUIRED_RAILS_VERSION)
|
32
30
|
end
|
data/docker-compose.yml
CHANGED
@@ -5,9 +5,10 @@ services:
|
|
5
5
|
build:
|
6
6
|
context: .
|
7
7
|
args:
|
8
|
-
NODE_MAJOR:
|
9
|
-
YARN_VERSION:
|
10
|
-
|
8
|
+
NODE_MAJOR: "12"
|
9
|
+
YARN_VERSION: "1.22.4"
|
10
|
+
RUBY_VERSION: ${RUBY_VERSION}
|
11
|
+
image: bootstrap-form:latest-$RUBY_VERSION
|
11
12
|
tmpfs:
|
12
13
|
- /tmp
|
13
14
|
|
@@ -17,15 +18,6 @@ services:
|
|
17
18
|
tty: true
|
18
19
|
volumes:
|
19
20
|
- .:/app:cached
|
20
|
-
# - rails_cache:/app/tmp/cache
|
21
|
-
# - bundle:/app/vendor/bundle
|
22
|
-
# - node_modules:/app/node_modules
|
23
|
-
# - packs:/app/public/packs
|
24
|
-
- /etc/passwd:/etc/passwd:ro
|
25
|
-
# One or the other of the following lines might be redundant, or one might be
|
26
|
-
# better than the other.
|
27
|
-
- ~/.ssh:${HOME}/.ssh
|
28
|
-
- ${SSH_AUTH_SOCK}:/ssh-agent
|
29
21
|
environment:
|
30
22
|
- SSH_AUTH_SOCK=/ssh-agent
|
31
23
|
- NODE_ENV=development
|
@@ -34,16 +26,6 @@ services:
|
|
34
26
|
- WEBPACKER_DEV_SERVER_HOST=webpacker
|
35
27
|
- WEB_CONCURRENCY=1
|
36
28
|
- HISTFILE=/app/.bash_history
|
29
|
+
ports:
|
30
|
+
- "3000:3000"
|
37
31
|
command: /bin/bash
|
38
|
-
|
39
|
-
# server:
|
40
|
-
# <<: *shell
|
41
|
-
# command: sh -c "cd demo/app && bundle exec rails server -b 0.0.0.0"
|
42
|
-
# ports:
|
43
|
-
# - '3000:3000'
|
44
|
-
|
45
|
-
# volumes:
|
46
|
-
# bundle:
|
47
|
-
# node_modules:
|
48
|
-
# rails_cache:
|
49
|
-
# packs:
|
data/gemfiles/6.0.gemfile
CHANGED
data/gemfiles/6.1.gemfile
CHANGED
data/gemfiles/7.0.gemfile
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
gems = "#{
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
2
2
|
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
3
3
|
|
4
|
-
# 7.0.0 has an issue with Ruby 3.1.
|
5
|
-
# And a test case has an issue with 7.0.1
|
6
4
|
gem "rails", "~> 7.0.2"
|
5
|
+
gem "sprockets-rails", require: "sprockets/railtie"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gemspec path: File.dirname(__dir__)
|
4
|
+
|
5
|
+
# To test with different Rails versions, use the files in `./gemfiles`
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "htmlbeautifier"
|
9
|
+
gem "puma"
|
10
|
+
gem "rubocop-performance", require: false
|
11
|
+
gem "rubocop-rails", require: false
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem "diffy"
|
16
|
+
gem "equivalent-xml"
|
17
|
+
gem "mocha"
|
18
|
+
gem "sqlite3"
|
19
|
+
end
|
20
|
+
|
21
|
+
group :development, :test do
|
22
|
+
gem "debug"
|
23
|
+
gem "pry-byebug"
|
24
|
+
end
|
25
|
+
|
26
|
+
group :ci do
|
27
|
+
gem "danger"
|
28
|
+
end
|
data/gemfiles/edge.gemfile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
gems = "#{
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
2
2
|
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
3
3
|
|
4
|
-
gem "rails", git: "https://github.com/rails/rails.git"
|
4
|
+
gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
|
5
|
+
gem "sprockets-rails", require: "sprockets/railtie"
|
@@ -24,14 +24,8 @@ module BootstrapForm
|
|
24
24
|
|
25
25
|
def label_classes(name, options, custom_label_col, group_layout)
|
26
26
|
classes = ["form-label", options[:class], label_layout_classes(custom_label_col, group_layout)]
|
27
|
-
|
28
|
-
|
29
|
-
when true
|
30
|
-
classes << "required"
|
31
|
-
when nil, :default
|
32
|
-
classes << "required" if required_attribute?(object, name)
|
33
|
-
end
|
34
|
-
|
27
|
+
classes << "required" if required_field_options(options, name)[:required]
|
28
|
+
options.delete(:required)
|
35
29
|
classes << "text-danger" if label_errors && error?(name)
|
36
30
|
classes.flatten.compact
|
37
31
|
end
|
@@ -46,7 +40,7 @@ module BootstrapForm
|
|
46
40
|
|
47
41
|
def label_text(name, options)
|
48
42
|
if label_errors && error?(name)
|
49
|
-
(options[:text] || object.class.human_attribute_name(name)).to_s
|
43
|
+
(options[:text] || object.class.human_attribute_name(name)).to_s + " #{get_error_messages(name)}"
|
50
44
|
else
|
51
45
|
options[:text] || object&.class.try(:human_attribute_name, name)
|
52
46
|
end
|