bootstrap_form 5.4.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer.json +38 -0
  3. data/.github/workflows/ruby.yml +11 -4
  4. data/.gitignore +20 -7
  5. data/.rubocop.yml +4 -6
  6. data/.yarnrc +1 -1
  7. data/CHANGELOG.md +3 -0
  8. data/CONTRIBUTING.md +33 -108
  9. data/DOCKER.md +95 -0
  10. data/Gemfile +5 -1
  11. data/README.md +135 -72
  12. data/RELEASING.md +2 -9
  13. data/Rakefile +23 -0
  14. data/bootstrap_form.gemspec +1 -1
  15. data/compose.yml +36 -0
  16. data/gemfiles/7.2.gemfile +9 -0
  17. data/gemfiles/8.0.gemfile +9 -0
  18. data/gemfiles/8.1.gemfile +9 -0
  19. data/gemfiles/common.gemfile +1 -2
  20. data/gemfiles/edge.gemfile +5 -1
  21. data/lib/bootstrap_form/action_view_extensions/form_helper.rb +6 -6
  22. data/lib/bootstrap_form/components/labels.rb +2 -2
  23. data/lib/bootstrap_form/components/validation.rb +0 -1
  24. data/lib/bootstrap_form/form_builder.rb +12 -6
  25. data/lib/bootstrap_form/form_group.rb +3 -3
  26. data/lib/bootstrap_form/form_group_builder.rb +2 -2
  27. data/lib/bootstrap_form/helpers/bootstrap.rb +6 -6
  28. data/lib/bootstrap_form/inputs/base.rb +8 -6
  29. data/lib/bootstrap_form/inputs/check_box.rb +11 -5
  30. data/lib/bootstrap_form/inputs/collection_check_boxes.rb +2 -8
  31. data/lib/bootstrap_form/inputs/file_field.rb +1 -1
  32. data/lib/bootstrap_form/inputs/range_field.rb +1 -1
  33. data/lib/bootstrap_form/inputs/rich_text_area.rb +2 -0
  34. data/lib/bootstrap_form/inputs/submit.rb +1 -1
  35. data/lib/bootstrap_form/inputs/text_area.rb +2 -0
  36. data/lib/bootstrap_form/version.rb +2 -2
  37. data/lib/bootstrap_form.rb +0 -10
  38. metadata +17 -17
  39. data/Dockerfile +0 -22
  40. data/docker-compose-system-test.yml +0 -45
  41. data/docker-compose.yml +0 -29
  42. data/gemfiles/6.1.gemfile +0 -4
  43. data/gemfiles/7.0.gemfile +0 -5
  44. data/gemfiles/7.1.gemfile +0 -5
data/README.md CHANGED
@@ -25,43 +25,64 @@ 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 3.0+ (https://www.ruby-lang.org/en/downloads/branches/)
29
- * Rails 6.1+ (https://guides.rubyonrails.org/maintenance_policy.html)
28
+ * Ruby 3.2+ (https://www.ruby-lang.org/en/downloads/branches/)
29
+ * Rails 7.2+ (https://guides.rubyonrails.org/maintenance_policy.html)
30
30
  * Bootstrap 5.0+
31
31
 
32
32
  ## Installation
33
33
 
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`:
34
+ This gem needs Bootstrap. The gem itself doesn't really care how Bootstrap is included in your application. There are many ways to install Bootstrap in a Rails application. Covering them all is beyond the scope of this README. However, here are some hints for a couple of common options.
35
35
 
36
- ```ruby
37
- gem "bootstrap", "~> 5.0"
36
+ If you're creating a new Rails app, create it with at least the following options:
37
+
38
+ ```bash
39
+ rails new --javascript=esbuild --css=bootstrap <application-name>
38
40
  ```
39
41
 
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`.
42
+ `esbuild` can be any of the options, _except_ the default `importmaps`.
43
+
44
+ If you have an existing project, and it's processing CSS and JavaScript with some sort of front-end preprocessor, then install Bootstrap for your front-end preprocessor. That's probably something like this:
45
+
46
+ ```bash
47
+ yarn add bootstrap popper.js
48
+ ```
49
+
50
+ You can use this gem with other ways of installing Bootstrap, but how to do so is outside the scope of this README.
41
51
 
42
- Add the `bootstrap_form` gem to your `Gemfile`:
52
+ Once Bootstrap is installed, add the `bootstrap_form` gem to your `Gemfile`:
43
53
 
44
54
  ```ruby
45
- gem "bootstrap_form", "~> 5.4"
55
+ gem "bootstrap_form", "~> 5.5"
46
56
  ```
47
57
 
48
58
  Then:
49
59
 
50
60
  `bundle install`
51
61
 
52
- Depending on which CSS pre-processor you are using, adding the bootstrap form styles differs slightly.
53
- If you use Rails in the default mode without any pre-processor, you'll have to add the following line to your `application.css` file:
62
+ `bootstrap_form` uses a very small number of its own CSS styles. These styles are used in HTML generated by the `error_summary` and `alert_message` error helpers, and the `date_select`, `time_select`, and `datetime_select` helpers. If you're not using those helpers, you don't need to install the `bootstrap_form` CSS styles.
54
63
 
55
- ```css
56
- *= require rails_bootstrap_forms
64
+ If you do need the CSS styles, add them to your CSS bundle (usually your `application.scss` file). The way to do this depends on whether you're using Propshaft (the Rails 8 default), or Sprockets (pre-Rails 8). (Check your `Gemfile` to see whether you're using `sprockets-rails` or `propshaft`.)
65
+
66
+ If you're using Propshaft, add the styles to your CSS bundle like this:
67
+
68
+ ```scss
69
+ @use "rails_bootstrap_forms";
57
70
  ```
58
71
 
59
- If you followed the [official bootstrap installation guide](https://github.com/twbs/bootstrap-rubygem#a-ruby-on-rails), you'll probably have switched to SCSS. In this case add the following line to your `application.scss`:
72
+ If you're using Sprockets, add the styles to your CSS bundle like this:
60
73
 
61
74
  ```scss
62
- @import "rails_bootstrap_forms";
75
+ @import "rails_bootstrap_forms.css";
63
76
  ```
64
77
 
78
+ If you're using Sprockets, you can also consider using the `bootstrap` gem to your `Gemfile`, as a way of installing Bootstrap itself. However, we haven't used this approach for a few years. Please report an issue if it doesn't work:
79
+
80
+ ```ruby
81
+ gem "bootstrap", "~> 5.0"
82
+ ```
83
+
84
+ 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`.
85
+
65
86
  ## Usage
66
87
 
67
88
  ### bootstrap_form_for
@@ -91,7 +112,7 @@ This generates the following HTML:
91
112
  <input class="form-control" id="user_password" name="user[password]" type="password">
92
113
  </div>
93
114
  <div class="form-check mb-3">
94
- <input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
115
+ <input name="user[remember_me]" type="hidden" value="0">
95
116
  <input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
96
117
  <label class="form-check-label" for="user_remember_me">Remember me</label>
97
118
  </div>
@@ -151,7 +172,7 @@ This generates:
151
172
  <small class="form-text text-muted">A good password should be at least six characters long</small>
152
173
  </div>
153
174
  <div class="form-check mb-3">
154
- <input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
175
+ <input name="user[remember_me]" type="hidden" value="0">
155
176
  <input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
156
177
  <label class="form-check-label" for="user_remember_me">Remember me</label>
157
178
  </div>
@@ -529,11 +550,25 @@ It's just a short form of `wrapper: { class: 'mb-3 additional-class' }`.
529
550
 
530
551
  If you don't want any class on the form group div, you can set it to `false`: `wrapper_class: false`.
531
552
 
553
+ ![Example 16](demo/doc/screenshots/bootstrap/readme/16_example.png "Example 16")
554
+ ```erb
555
+ <%= f.text_field :name, wrapper: { class: false } %>
556
+ ```
557
+
558
+ This generates:
559
+
560
+ ```html
561
+ <div>
562
+ <label class="form-label" for="user_name">Name</label>
563
+ <input class="form-control" id="user_name" name="user[name]" type="text">
564
+ </div>
565
+ ```
566
+
532
567
  ### Suppressing the Form Group Altogether
533
568
 
534
569
  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:
535
570
 
536
- ![Example 16](demo/doc/screenshots/bootstrap/readme/16_example.png "Example 16")
571
+ ![Example 17](demo/doc/screenshots/bootstrap/readme/17_example.png "Example 17")
537
572
  ```erb
538
573
  <%= f.form_group :user do %>
539
574
  <%= f.email_field :email, wrapper: false %>
@@ -554,7 +589,7 @@ Note that Bootstrap relies on the form group div to correctly format most fields
554
589
 
555
590
  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:
556
591
 
557
- ![Example 17](demo/doc/screenshots/bootstrap/readme/17_example.png "Example 17")
592
+ ![Example 18](demo/doc/screenshots/bootstrap/readme/18_example.png "Example 18")
558
593
  ```erb
559
594
  <%= f.select :product, [["Apple", 1], ["Grape", 2]], { label: "Choose your favorite fruit:", wrapper: { class: 'has-warning', data: { foo: 'bar' } } }, { class: "selectpicker" } %>
560
595
  ```
@@ -577,7 +612,7 @@ Checkboxes and radios should be placed inside of a `form_group` to render
577
612
  properly. The following example ensures that the entire form group will display
578
613
  an error if an associated validations fails:
579
614
 
580
- ![Example 18](demo/doc/screenshots/bootstrap/readme/18_example.png "Example 18")
615
+ ![Example 19](demo/doc/screenshots/bootstrap/readme/19_example.png "Example 19")
581
616
  ```erb
582
617
  <%= f.form_group :skill_level, label: { text: "Skill" }, help: "Optional Help Text" do %>
583
618
  <%= f.radio_button :skill_level, 0, label: "Novice", checked: true %>
@@ -611,7 +646,7 @@ This generates:
611
646
  </div>
612
647
  <div class="mb-3">
613
648
  <div class="form-check mb-3">
614
- <input autocomplete="off" name="user[terms]" type="hidden" value="0">
649
+ <input name="user[terms]" type="hidden" value="0">
615
650
  <input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1">
616
651
  <label class="form-check-label" for="user_terms">I agree to the Terms of Service</label>
617
652
  </div>
@@ -620,7 +655,7 @@ This generates:
620
655
 
621
656
  You can also create a checkbox using a block:
622
657
 
623
- ![Example 19](demo/doc/screenshots/bootstrap/readme/19_example.png "Example 19")
658
+ ![Example 20](demo/doc/screenshots/bootstrap/readme/20_example.png "Example 20")
624
659
  ```erb
625
660
  <%= f.form_group :terms, label: { text: "Optional Label" } do %>
626
661
  <%= f.check_box :terms do %>
@@ -635,7 +670,7 @@ This generates:
635
670
  <div class="mb-3">
636
671
  <label class="form-label" for="user_terms">Optional Label</label>
637
672
  <div class="form-check mb-3">
638
- <input autocomplete="off" name="user[terms]" type="hidden" value="0">
673
+ <input name="user[terms]" type="hidden" value="0">
639
674
  <input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1">
640
675
  <label class="form-check-label" for="user_terms">
641
676
  You need to check this box to accept our terms of service and privacy policy
@@ -646,7 +681,7 @@ This generates:
646
681
 
647
682
  To display checkboxes and radios inline, pass the `inline: true` option:
648
683
 
649
- ![Example 20](demo/doc/screenshots/bootstrap/readme/20_example.png "Example 20")
684
+ ![Example 21](demo/doc/screenshots/bootstrap/readme/21_example.png "Example 21")
650
685
  ```erb
651
686
  <%= f.form_group :skill_level, label: { text: "Skill" } do %>
652
687
  <%= f.radio_button :skill_level, 0, label: "Novice", inline: true %>
@@ -677,7 +712,7 @@ This generates:
677
712
 
678
713
  Check boxes and radio buttons are wrapped in a `div.form-check`. You can add classes to this `div` with the `:wrapper_class` option:
679
714
 
680
- ![Example 21](demo/doc/screenshots/bootstrap/readme/21_example.png "Example 21")
715
+ ![Example 22](demo/doc/screenshots/bootstrap/readme/22_example.png "Example 22")
681
716
  ```erb
682
717
  <%= f.radio_button :skill_level, 0, label: "Novice", inline: true, wrapper_class: "w-auto" %>
683
718
  ```
@@ -693,7 +728,7 @@ This generates:
693
728
 
694
729
  You can also add a style to the tag using the `wrapper` option:
695
730
 
696
- ![Example 22](demo/doc/screenshots/bootstrap/readme/22_example.png "Example 22")
731
+ ![Example 23](demo/doc/screenshots/bootstrap/readme/23_example.png "Example 23")
697
732
  ```erb
698
733
  <%= f.check_box :skilled, inline: true, wrapper: {style: "color: green"} %>
699
734
  <%= f.radio_button :skill_level, 0, label: "Novice", inline: true, wrapper: {class: 'w-auto', style: "color: red"} %>
@@ -703,7 +738,7 @@ This generates:
703
738
 
704
739
  ```html
705
740
  <div class="form-check form-check-inline mb-3" style="color: green">
706
- <input autocomplete="off" name="user[skilled]" type="hidden" value="0">
741
+ <input name="user[skilled]" type="hidden" value="0">
707
742
  <input class="form-check-input" id="user_skilled" name="user[skilled]" type="checkbox" value="1">
708
743
  <label class="form-check-label" for="user_skilled">Skilled</label>
709
744
  </div>
@@ -717,7 +752,7 @@ This generates:
717
752
 
718
753
  To render checkboxes as switches with Bootstrap 4.2+, use `switch: true`:
719
754
 
720
- ![Example 23](demo/doc/screenshots/bootstrap/readme/23_example.png "Example 23")
755
+ ![Example 24](demo/doc/screenshots/bootstrap/readme/24_example.png "Example 24")
721
756
  ```erb
722
757
  <%= f.check_box :remember_me, switch: true %>
723
758
  ```
@@ -726,7 +761,7 @@ This generates:
726
761
 
727
762
  ```html
728
763
  <div class="form-check mb-3 form-switch">
729
- <input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
764
+ <input name="user[remember_me]" type="hidden" value="0">
730
765
  <input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
731
766
  <label class="form-check-label" for="user_remember_me">Remember me</label>
732
767
  </div>
@@ -737,7 +772,7 @@ This generates:
737
772
  `bootstrap_form` also provides helpers that automatically create the
738
773
  `form_group` and the `radio_button`s or `check_box`es for you:
739
774
 
740
- ![Example 24](demo/doc/screenshots/bootstrap/readme/24_example.png "Example 24")
775
+ ![Example 25](demo/doc/screenshots/bootstrap/readme/25_example.png "Example 25")
741
776
  ```erb
742
777
  <%= f.collection_radio_buttons :skill_level, Skill.all, :id, :name %>
743
778
  <%= f.collection_check_boxes :skills, Skill.all, :id, :name %>
@@ -757,7 +792,7 @@ This generates:
757
792
  <label class="form-check-label" for="user_skill_level_2">Farming</label>
758
793
  </div>
759
794
  </div>
760
- <input autocomplete="off" id="user_skills" name="user[skills][]" type="hidden" value="">
795
+ <input id="user_skills" name="user[skills][]" type="hidden" value="">
761
796
  <div class="mb-3">
762
797
  <label class="form-label" for="user_skills">Skills</label>
763
798
  <div class="form-check">
@@ -783,7 +818,7 @@ Collection methods accept these options:
783
818
 
784
819
  To add `data-` attributes to a collection of radio buttons, map your models to an array and add a hash:
785
820
 
786
- ![Example 25](demo/doc/screenshots/bootstrap/readme/25_example.png "Example 25")
821
+ ![Example 26](demo/doc/screenshots/bootstrap/readme/26_example.png "Example 26")
787
822
  ```erb
788
823
  <%# Use the :first and :second elements of the array to be the value and label respectively %>
789
824
  <%- choices = @collection.map { |addr| [ addr.id, addr.street, { 'data-zip-code': addr.zip_code } ] } -%>
@@ -811,7 +846,7 @@ This generates:
811
846
 
812
847
  You can create a range control like this:
813
848
 
814
- ![Example 26](demo/doc/screenshots/bootstrap/readme/26_example.png "Example 26")
849
+ ![Example 27](demo/doc/screenshots/bootstrap/readme/27_example.png "Example 27")
815
850
  ```erb
816
851
  <%= f.range_field :excellence %>
817
852
  ```
@@ -829,7 +864,7 @@ This generates:
829
864
 
830
865
  You can create a static control like this:
831
866
 
832
- ![Example 27](demo/doc/screenshots/bootstrap/readme/27_example.png "Example 27")
867
+ ![Example 28](demo/doc/screenshots/bootstrap/readme/28_example.png "Example 28")
833
868
  ```erb
834
869
  <%= f.static_control :email %>
835
870
  ```
@@ -845,7 +880,7 @@ This generates:
845
880
 
846
881
  Here's the output for a horizontal layout:
847
882
 
848
- ![Example 28](demo/doc/screenshots/bootstrap/readme/28_example.png "Example 28")
883
+ ![Example 29](demo/doc/screenshots/bootstrap/readme/29_example.png "Example 29")
849
884
  ```erb
850
885
  <%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
851
886
  <%= f.static_control :email %>
@@ -867,7 +902,7 @@ This generates:
867
902
 
868
903
  You can also create a static control that isn't based on a model attribute:
869
904
 
870
- ![Example 29](demo/doc/screenshots/bootstrap/readme/29_example.png "Example 29")
905
+ ![Example 30](demo/doc/screenshots/bootstrap/readme/30_example.png "Example 30")
871
906
  ```erb
872
907
  <%= f.static_control :field_name, label: "Custom Static Control", value: "Content Here" %>
873
908
  ```
@@ -885,7 +920,7 @@ This generates:
885
920
 
886
921
  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:
887
922
 
888
- ![Example 30](demo/doc/screenshots/bootstrap/readme/30_example.png "Example 30")
923
+ ![Example 31](demo/doc/screenshots/bootstrap/readme/31_example.png "Example 31")
889
924
  ```erb
890
925
  <%= f.static_control label: "Custom Static Control", value: "Content Here", name: nil %>
891
926
  ```
@@ -906,7 +941,25 @@ The value of the block would be used for the content of the static "control".
906
941
  Bootstrap 4 actually creates and styles a disabled input field for static controls, so the value of the control has to be specified by the `value:` option.
907
942
  Passing a block to `static_control` no longer has any effect.
908
943
 
909
- ## Date Helpers
944
+ ## Date and Time Helpers
945
+
946
+ You can create a date picker, time picker, or date-time picker with `date_field`, `time_field`, or `datetime_field`, like this:
947
+
948
+ ![Example 32](demo/doc/screenshots/bootstrap/readme/32_example.png "Example 32")
949
+ ```erb
950
+ <%= f.date_field :joined_at, class: "w-auto" %>
951
+ ```
952
+
953
+ This generates:
954
+
955
+ ```html
956
+ <div class="mb-3">
957
+ <label class="form-label" for="user_joined_at">Joined at</label>
958
+ <input class="form-control w-auto" id="user_joined_at" name="user[joined_at]" type="date">
959
+ </div>
960
+ ```
961
+
962
+ For backwards compatibility, there are also helpers for `date_select`, `time_select`, and `datetime_select`.
910
963
 
911
964
  The multiple selects that the date and time helpers (`date_select`,
912
965
  `time_select`, `datetime_select`) generate are wrapped inside a
@@ -919,7 +972,7 @@ this by defining these selects as `inline-block` and a width of `auto`.
919
972
  The `btn btn-secondary` CSS classes are automatically added to your submit
920
973
  buttons.
921
974
 
922
- ![Example 31](demo/doc/screenshots/bootstrap/readme/31_example.png "Example 31")
975
+ ![Example 33](demo/doc/screenshots/bootstrap/readme/33_example.png "Example 33")
923
976
  ```erb
924
977
  <%= f.submit %>
925
978
  ```
@@ -933,7 +986,7 @@ This generates:
933
986
  You can also use the `primary` helper, which adds `btn btn-primary` to your
934
987
  submit button:
935
988
 
936
- ![Example 32](demo/doc/screenshots/bootstrap/readme/32_example.png "Example 32")
989
+ ![Example 34](demo/doc/screenshots/bootstrap/readme/34_example.png "Example 34")
937
990
  ```erb
938
991
  <%= f.primary "Optional Label" %>
939
992
  ```
@@ -946,7 +999,7 @@ This generates:
946
999
 
947
1000
  You can specify your own classes like this:
948
1001
 
949
- ![Example 33](demo/doc/screenshots/bootstrap/readme/33_example.png "Example 33")
1002
+ ![Example 35](demo/doc/screenshots/bootstrap/readme/35_example.png "Example 35")
950
1003
  ```erb
951
1004
  <%= f.submit "Log In", class: "btn btn-success" %>
952
1005
  ```
@@ -962,7 +1015,7 @@ it will be rendered as an HTML button, instead of an input tag. This allows you
962
1015
  to specify HTML content and styling for your buttons (such as adding
963
1016
  illustrative icons to them). For example, the following statements
964
1017
 
965
- ![Example 34](demo/doc/screenshots/bootstrap/readme/34_example.png "Example 34")
1018
+ ![Example 36](demo/doc/screenshots/bootstrap/readme/36_example.png "Example 36")
966
1019
  ```erb
967
1020
  <%= f.primary "Save changes <span class='bi bi-save'></span>".html_safe, render_as_button: true %>
968
1021
 
@@ -996,7 +1049,7 @@ Bootstrap classes), or for element targeting via CSS classes.
996
1049
  Be aware, however, that using the `class` option will discard any extra classes
997
1050
  you add. As an example, the following button declarations
998
1051
 
999
- ![Example 35](demo/doc/screenshots/bootstrap/readme/35_example.png "Example 35")
1052
+ ![Example 37](demo/doc/screenshots/bootstrap/readme/37_example.png "Example 37")
1000
1053
  ```erb
1001
1054
  <%= f.primary "My Nice Button", extra_class: 'my-button' %>
1002
1055
 
@@ -1014,7 +1067,7 @@ will be rendered as
1014
1067
 
1015
1068
  ## Rich Text Areas AKA Trix Editor
1016
1069
 
1017
- ![Example 36](demo/doc/screenshots/bootstrap/readme/36_example.png "Example 36")
1070
+ ![Example 38](demo/doc/screenshots/bootstrap/readme/38_example.png "Example 38")
1018
1071
  ```erb
1019
1072
  <%= f.rich_text_area(:life_story) %>
1020
1073
  ```
@@ -1024,7 +1077,7 @@ will be rendered as:
1024
1077
  ```html
1025
1078
  <div class="mb-3">
1026
1079
  <label class="form-label" for="user_life_story">Life story</label>
1027
- <input autocomplete="off" id="user_life_story_trix_input_user" name="user[life_story]" type="hidden">
1080
+ <input id="user_life_story_trix_input_user" name="user[life_story]" type="hidden">
1028
1081
  <trix-toolbar id="trix-toolbar-1">
1029
1082
  <div class="trix-button-row">
1030
1083
  <span class="trix-button-group trix-button-group--text-tools" data-trix-button-group="text-tools">
@@ -1064,7 +1117,7 @@ will be rendered as:
1064
1117
  </div>
1065
1118
  </div>
1066
1119
  </trix-toolbar>
1067
- <trix-editor aria-label="Life story" class="trix-content form-control" contenteditable="" data-blob-url-template="http://shell:3001/rails/active_storage/blobs/redirect/:signed_id/:filename" data-direct-upload-url="http://shell:3001/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">
1120
+ <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">
1068
1121
  </trix-editor>
1069
1122
  </div>
1070
1123
  ```
@@ -1082,7 +1135,7 @@ The `hidden_field` helper in `bootstrap_form` calls the Rails helper directly, a
1082
1135
  If you want to use the original Rails form helpers for a particular field,
1083
1136
  append `_without_bootstrap` to the helper:
1084
1137
 
1085
- ![Example 37](demo/doc/screenshots/bootstrap/readme/37_example.png "Example 37")
1138
+ ![Example 39](demo/doc/screenshots/bootstrap/readme/39_example.png "Example 39")
1086
1139
  ```erb
1087
1140
  <%= f.text_field_without_bootstrap :email %>
1088
1141
  ```
@@ -1104,7 +1157,7 @@ To use an inline-layout form, use the `layout: :inline` option. To hide labels,
1104
1157
  use the `hide_label: true` option, which keeps your labels accessible to those
1105
1158
  using screen readers.
1106
1159
 
1107
- ![Example 38](demo/doc/screenshots/bootstrap/readme/38_example.png "Example 38")
1160
+ ![Example 40](demo/doc/screenshots/bootstrap/readme/40_example.png "Example 40")
1108
1161
  ```erb
1109
1162
  <%= bootstrap_form_for(@user, layout: :inline) do |f| %>
1110
1163
  <%= f.email_field :email, hide_label: true %>
@@ -1128,7 +1181,7 @@ This generates:
1128
1181
  </div>
1129
1182
  <div class="col">
1130
1183
  <div class="form-check form-check-inline">
1131
- <input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
1184
+ <input name="user[remember_me]" type="hidden" value="0">
1132
1185
  <input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
1133
1186
  <label class="form-check-label" for="user_remember_me">Remember me</label>
1134
1187
  </div>
@@ -1141,7 +1194,7 @@ This generates:
1141
1194
 
1142
1195
  To skip label rendering at all, use `skip_label: true` option.
1143
1196
 
1144
- ![Example 39](demo/doc/screenshots/bootstrap/readme/39_example.png "Example 39")
1197
+ ![Example 41](demo/doc/screenshots/bootstrap/readme/41_example.png "Example 41")
1145
1198
  ```erb
1146
1199
  <%= f.password_field :password, skip_label: true %>
1147
1200
  ```
@@ -1163,7 +1216,7 @@ To use a horizontal-layout form with labels to the left of the control, use the
1163
1216
  In the example below, the submit button has been wrapped in a `form_group` to
1164
1217
  keep it properly aligned.
1165
1218
 
1166
- ![Example 40](demo/doc/screenshots/bootstrap/readme/40_example.png "Example 40")
1219
+ ![Example 42](demo/doc/screenshots/bootstrap/readme/42_example.png "Example 42")
1167
1220
  ```erb
1168
1221
  <%= bootstrap_form_for(@user, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10") do |f| %>
1169
1222
  <%= f.email_field :email %>
@@ -1194,7 +1247,7 @@ This generates:
1194
1247
  <div class="mb-3 row">
1195
1248
  <div class="col-sm-10 offset-sm-2">
1196
1249
  <div class="form-check">
1197
- <input autocomplete="off" name="user[remember_me]" type="hidden" value="0">
1250
+ <input name="user[remember_me]" type="hidden" value="0">
1198
1251
  <input class="form-check-input" id="user_remember_me" name="user[remember_me]" type="checkbox" value="1">
1199
1252
  <label class="form-check-label" for="user_remember_me">Remember me</label>
1200
1253
  </div>
@@ -1210,7 +1263,7 @@ This generates:
1210
1263
 
1211
1264
  The `label_col` and `control_col` css classes can also be changed per control:
1212
1265
 
1213
- ![Example 41](demo/doc/screenshots/bootstrap/readme/41_example.png "Example 41")
1266
+ ![Example 43](demo/doc/screenshots/bootstrap/readme/43_example.png "Example 43")
1214
1267
  ```erb
1215
1268
  <%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
1216
1269
  <%= f.email_field :email %>
@@ -1241,7 +1294,7 @@ This generates:
1241
1294
  <div class="mb-3 row">
1242
1295
  <div class="col-sm-10">
1243
1296
  <div class="form-check">
1244
- <input autocomplete="off" name="user[terms]" type="hidden" value="0">
1297
+ <input name="user[terms]" type="hidden" value="0">
1245
1298
  <input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1">
1246
1299
  <label class="form-check-label" for="user_terms">Terms</label>
1247
1300
  </div>
@@ -1277,7 +1330,7 @@ end
1277
1330
 
1278
1331
  Control col wrapper class can be modified with `add_control_col_class`. This option will preserve column definition:
1279
1332
 
1280
- ![Example 42](demo/doc/screenshots/bootstrap/readme/42_example.png "Example 42")
1333
+ ![Example 44](demo/doc/screenshots/bootstrap/readme/44_example.png "Example 44")
1281
1334
  ```erb
1282
1335
  <%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
1283
1336
  <%= f.email_field :email %>
@@ -1316,7 +1369,7 @@ This generates:
1316
1369
 
1317
1370
  The form-level `layout` can be overridden per field, unless the form-level layout was `inline`:
1318
1371
 
1319
- ![Example 43](demo/doc/screenshots/bootstrap/readme/43_example.png "Example 43")
1372
+ ![Example 45](demo/doc/screenshots/bootstrap/readme/45_example.png "Example 45")
1320
1373
  ```erb
1321
1374
  <%= bootstrap_form_for(@user, layout: :horizontal) do |f| %>
1322
1375
  <%= f.email_field :email %>
@@ -1355,7 +1408,7 @@ This generates:
1355
1408
  </div>
1356
1409
  <div class="mb-3">
1357
1410
  <div class="form-check">
1358
- <input autocomplete="off" name="user[terms]" type="hidden" value="0">
1411
+ <input name="user[terms]" type="hidden" value="0">
1359
1412
  <input class="form-check-input" id="user_terms" name="user[terms]" type="checkbox" value="1">
1360
1413
  <label class="form-check-label" for="user_terms">Terms</label>
1361
1414
  </div>
@@ -1371,7 +1424,7 @@ A form-level `layout: :inline` can't be overridden because of the way Bootstrap
1371
1424
  The `floating` option can be used to enable Bootstrap 5's floating labels. This option is supported on text fields
1372
1425
  and dropdowns. Here's an example:
1373
1426
 
1374
- ![Example 44](demo/doc/screenshots/bootstrap/readme/44_example.png "Example 44")
1427
+ ![Example 46](demo/doc/screenshots/bootstrap/readme/46_example.png "Example 46")
1375
1428
  ```erb
1376
1429
  <%= bootstrap_form_for(@user) do |f| %>
1377
1430
  <%= f.email_field :email, floating: true %>
@@ -1419,7 +1472,7 @@ Rails normally wraps fields with validation errors in a `div.field_with_errors`,
1419
1472
  By default, fields that have validation errors will be outlined in red and the
1420
1473
  error will be displayed below the field. Here's an example:
1421
1474
 
1422
- ![Example 45](demo/doc/screenshots/bootstrap/readme/45_example.png "Example 45")
1475
+ ![Example 47](demo/doc/screenshots/bootstrap/readme/47_example.png "Example 47")
1423
1476
  ```erb
1424
1477
  <%= bootstrap_form_for(@user_with_error) do |f| %>
1425
1478
  <%= f.email_field :email %>
@@ -1452,7 +1505,7 @@ Generated HTML:
1452
1505
  <div class="invalid-feedback">is invalid</div>
1453
1506
  </div>
1454
1507
  </div>
1455
- <input autocomplete="off" id="user_preferences" name="user[preferences][]" type="hidden" value="">
1508
+ <input id="user_preferences" name="user[preferences][]" type="hidden" value="">
1456
1509
  <div class="mb-3">
1457
1510
  <label class="form-label" for="user_preferences">Preferences</label>
1458
1511
  <div class="form-check">
@@ -1486,7 +1539,7 @@ You can turn off inline errors for the entire form like this:
1486
1539
  You can also display validation errors in the field's label; just turn
1487
1540
  on the `:label_errors` option. Here's an example:
1488
1541
 
1489
- ![Example 46](demo/doc/screenshots/bootstrap/readme/46_example.png "Example 46")
1542
+ ![Example 48](demo/doc/screenshots/bootstrap/readme/48_example.png "Example 48")
1490
1543
  ```erb
1491
1544
  <%= bootstrap_form_for(@user_with_error, label_errors: true) do |f| %>
1492
1545
  <%= f.email_field :email %>
@@ -1519,7 +1572,7 @@ To display an error message with an error summary, you can use the
1519
1572
  `alert_message` helper. This won't output anything unless a model validation
1520
1573
  has failed.
1521
1574
 
1522
- ![Example 47](demo/doc/screenshots/bootstrap/readme/47_example.png "Example 47")
1575
+ ![Example 49](demo/doc/screenshots/bootstrap/readme/49_example.png "Example 49")
1523
1576
  ```erb
1524
1577
  <%= bootstrap_form_for @user_with_error do |f| %>
1525
1578
  <%= f.alert_message "Please fix the errors below." %>
@@ -1543,7 +1596,7 @@ Which outputs:
1543
1596
 
1544
1597
  You can turn off the error summary like this:
1545
1598
 
1546
- ![Example 48](demo/doc/screenshots/bootstrap/readme/48_example.png "Example 48")
1599
+ ![Example 50](demo/doc/screenshots/bootstrap/readme/50_example.png "Example 50")
1547
1600
  ```erb
1548
1601
  <%= bootstrap_form_for @user_with_error do |f| %>
1549
1602
  <%= f.alert_message "Please fix the errors below.", error_summary: false %>
@@ -1560,7 +1613,7 @@ This generates:
1560
1613
 
1561
1614
  To output a simple unordered list of errors, use the `error_summary` helper.
1562
1615
 
1563
- ![Example 49](demo/doc/screenshots/bootstrap/readme/49_example.png "Example 49")
1616
+ ![Example 51](demo/doc/screenshots/bootstrap/readme/51_example.png "Example 51")
1564
1617
  ```erb
1565
1618
  <%= bootstrap_form_for @user_with_error do |f| %>
1566
1619
  <%= f.error_summary %>
@@ -1583,9 +1636,10 @@ Which outputs:
1583
1636
 
1584
1637
  If you want to display a custom inline error for a specific attribute not represented by a form field, use the `errors_on` helper.
1585
1638
 
1586
- ![Example 50](demo/doc/screenshots/bootstrap/readme/50_example.png "Example 50")
1639
+ ![Example 52](demo/doc/screenshots/bootstrap/readme/52_example.png "Example 52")
1587
1640
  ```erb
1588
1641
  <%= bootstrap_form_for @user_with_error do |f| %>
1642
+ <input class="is-invalid" autocomplete="off" disabled type="hidden">
1589
1643
  <%= f.errors_on :email %>
1590
1644
  <% end %>
1591
1645
  ```
@@ -1594,15 +1648,19 @@ Which outputs:
1594
1648
 
1595
1649
  ```html
1596
1650
  <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1651
+ <input autocomplete="off" class="is-invalid" disabled type="hidden">
1597
1652
  <div class="invalid-feedback">Email is invalid</div>
1598
1653
  </form>
1599
1654
  ```
1600
1655
 
1656
+ Note that the `invalid-feedback` `div` is hidden unless there is a preceding element under the same parent that has class `is-invalid`. For the examples, we've artificially added a hidden input.
1657
+
1601
1658
  You can hide the attribute name like this:
1602
1659
 
1603
- ![Example 51](demo/doc/screenshots/bootstrap/readme/51_example.png "Example 51")
1660
+ ![Example 53](demo/doc/screenshots/bootstrap/readme/53_example.png "Example 53")
1604
1661
  ```erb
1605
1662
  <%= bootstrap_form_for @user_with_error do |f| %>
1663
+ <input class="is-invalid" autocomplete="off" disabled type="hidden">
1606
1664
  <%= f.errors_on :email, hide_attribute_name: true %>
1607
1665
  <% end %>
1608
1666
  ```
@@ -1611,15 +1669,17 @@ Which outputs:
1611
1669
 
1612
1670
  ```html
1613
1671
  <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1672
+ <input autocomplete="off" class="is-invalid" disabled type="hidden">
1614
1673
  <div class="invalid-feedback">is invalid</div>
1615
1674
  </form>
1616
1675
  ```
1617
1676
 
1618
1677
  You can also use a custom class for the wrapping div, like this:
1619
1678
 
1620
- ![Example 52](demo/doc/screenshots/bootstrap/readme/52_example.png "Example 52")
1679
+ ![Example 54](demo/doc/screenshots/bootstrap/readme/54_example.png "Example 54")
1621
1680
  ```erb
1622
1681
  <%= bootstrap_form_for @user_with_error do |f| %>
1682
+ <input class="is-invalid" autocomplete="off" disabled type="hidden">
1623
1683
  <%= f.errors_on :email, custom_class: 'custom-error' %>
1624
1684
  <% end %>
1625
1685
  ```
@@ -1628,10 +1688,13 @@ Which outputs:
1628
1688
 
1629
1689
  ```html
1630
1690
  <form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
1691
+ <input autocomplete="off" class="is-invalid" disabled type="hidden">
1631
1692
  <div class="custom-error">Email is invalid</div>
1632
1693
  </form>
1633
1694
  ```
1634
1695
 
1696
+ Note that adding the custom class removes the default `invalid-feedback` class. If you still want the default `invalid-feedback` formatting, add it to your `custom_class`es.
1697
+
1635
1698
  ## Required Fields
1636
1699
 
1637
1700
  A label that is associated with a required field is automatically annotated with
@@ -1652,7 +1715,7 @@ ActiveModel::Validations::PresenceValidator.
1652
1715
 
1653
1716
  In cases where this behaviour is undesirable, use the `required` option to force the class to be present or absent:
1654
1717
 
1655
- ![Example 53](demo/doc/screenshots/bootstrap/readme/53_example.png "Example 53")
1718
+ ![Example 55](demo/doc/screenshots/bootstrap/readme/55_example.png "Example 55")
1656
1719
  ```erb
1657
1720
  <%= f.password_field :login, label: "New Username", required: true %>
1658
1721
  <%= f.password_field :password, label: "New Password", required: false %>
@@ -1675,7 +1738,7 @@ This generates:
1675
1738
 
1676
1739
  Adding a form control for a `belongs_to` field will automatically pick up the associated presence validator.
1677
1740
 
1678
- ![Example 54](demo/doc/screenshots/bootstrap/readme/54_example.png "Example 54")
1741
+ ![Example 56](demo/doc/screenshots/bootstrap/readme/56_example.png "Example 56")
1679
1742
  ```erb
1680
1743
  <%= bootstrap_form_for(@address, url: '/address') do |f| %>
1681
1744
  <%= f.collection_select :user_id, @users, :id, :email, include_blank: "Select a value" %>
@@ -1703,8 +1766,8 @@ Generated HTML:
1703
1766
  <input class="form-control" id="address_street" name="address[street]" type="text" value="Foo">
1704
1767
  </div>
1705
1768
  <div class="mb-3">
1706
- <label class="form-label" for="address_city">City</label>
1707
- <input class="form-control" id="address_city" name="address[city]" type="text">
1769
+ <label class="form-label required" for="address_city">City</label>
1770
+ <input class="form-control" id="address_city" name="address[city]" required="required" type="text">
1708
1771
  </div>
1709
1772
  <div class="mb-3">
1710
1773
  <label class="form-label" for="address_state">State</label>
@@ -1722,7 +1785,7 @@ Generated HTML:
1722
1785
 
1723
1786
  Fields can be disabled using the standard Rails form helper option.
1724
1787
 
1725
- ![Example 55](demo/doc/screenshots/bootstrap/readme/55_example.png "Example 55")
1788
+ ![Example 57](demo/doc/screenshots/bootstrap/readme/57_example.png "Example 57")
1726
1789
  ```erb
1727
1790
  <%= bootstrap_form_for @user do |f| %>
1728
1791
  <div class="row g-3">
@@ -1784,7 +1847,7 @@ Generated HTML:
1784
1847
  </div>
1785
1848
  <div class="col-auto">
1786
1849
  <div class="form-check mb-3">
1787
- <input autocomplete="off" disabled name="user[terms]" type="hidden" value="0">
1850
+ <input disabled name="user[terms]" type="hidden" value="0">
1788
1851
  <input class="form-check-input" disabled id="user_terms" name="user[terms]" type="checkbox" value="1">
1789
1852
  <label class="form-check-label" for="user_terms">Terms</label>
1790
1853
  </div>