Skip to content

Commit 3530be9

Browse files
committed
aria-labelledby for errors
Fix line lengths
1 parent 2bcb4dd commit 3530be9

8 files changed

Lines changed: 32 additions & 20 deletions

File tree

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,38 +1493,38 @@ Generated HTML:
14931493
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
14941494
<div class="mb-3">
14951495
<label class="form-label required" for="user_email">Email</label>
1496-
<input class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
1497-
<div class="invalid-feedback">is invalid</div>
1496+
<input aria-labelledby="user_email_feedback" class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
1497+
<div class="invalid-feedback" id="user_email_feedback">is invalid</div>
14981498
</div>
14991499
<div aria-labelledby="user_misc" class="mb-3" role="group">
15001500
<div class="form-label" id="user_misc">Misc</div>
15011501
<div class="form-check">
1502-
<input checked class="form-check-input is-invalid" id="user_misc_1" name="user[misc]" type="radio" value="1">
1502+
<input aria-labelledby="user_misc_feedback" checked class="form-check-input is-invalid" id="user_misc_1" name="user[misc]" type="radio" value="1">
15031503
<label class="form-check-label" for="user_misc_1">Mind reading</label>
15041504
</div>
15051505
<div class="form-check">
1506-
<input class="form-check-input is-invalid" id="user_misc_2" name="user[misc]" type="radio" value="2">
1506+
<input aria-labelledby="user_misc_feedback" class="form-check-input is-invalid" id="user_misc_2" name="user[misc]" type="radio" value="2">
15071507
<label class="form-check-label" for="user_misc_2">Farming</label>
1508-
<div class="invalid-feedback">is invalid</div>
1508+
<div class="invalid-feedback" id="user_misc_feedback">is invalid</div>
15091509
</div>
15101510
</div>
15111511
<input id="user_preferences" name="user[preferences][]" type="hidden" value="">
15121512
<div aria-labelledby="user_preferences" class="mb-3" role="group">
15131513
<div class="form-label" id="user_preferences">Preferences</div>
15141514
<div class="form-check">
1515-
<input checked class="form-check-input is-invalid" id="user_preferences_1" name="user[preferences][]" type="checkbox" value="1">
1515+
<input aria-labelledby="user_preferences_feedback" checked class="form-check-input is-invalid" id="user_preferences_1" name="user[preferences][]" type="checkbox" value="1">
15161516
<label class="form-check-label" for="user_preferences_1">Good</label>
15171517
</div>
15181518
<div class="form-check">
1519-
<input class="form-check-input is-invalid" id="user_preferences_2" name="user[preferences][]" type="checkbox" value="2">
1519+
<input aria-labelledby="user_preferences_feedback" class="form-check-input is-invalid" id="user_preferences_2" name="user[preferences][]" type="checkbox" value="2">
15201520
<label class="form-check-label" for="user_preferences_2">Bad</label>
1521-
<div class="invalid-feedback">is invalid</div>
1521+
<div class="invalid-feedback" id="user_preferences_feedback">is invalid</div>
15221522
</div>
15231523
</div>
15241524
<div class="mb-3">
15251525
<label class="form-label" for="user_address_attributes_street">Street</label>
1526-
<input class="form-control is-invalid" id="user_address_attributes_street" name="user[address_attributes][street]" type="text" value="Bar">
1527-
<div class="invalid-feedback">is invalid</div>
1526+
<input aria-labelledby="user_address_attributes_street_feedback" class="form-control is-invalid" id="user_address_attributes_street" name="user[address_attributes][street]" type="text" value="Bar">
1527+
<div class="invalid-feedback" id="user_address_attributes_street_feedback">is invalid</div>
15281528
</div>
15291529
</form>
15301530
```
@@ -1554,8 +1554,8 @@ Generated HTML:
15541554
```html
15551555
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
15561556
<div class="mb-3">
1557-
<label class="form-label required text-danger" for="user_email">Email is invalid</label>
1558-
<input class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
1557+
<label class="form-label required text-danger" for="user_email" id="user_email_feedback">Email is invalid</label>
1558+
<input aria-labelledby="user_email_feedback" class="form-control is-invalid" id="user_email" name="user[email]" required="required" type="email" value="steve.example.com">
15591559
</div>
15601560
</form>
15611561
```
@@ -1652,7 +1652,7 @@ Which outputs:
16521652
```html
16531653
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
16541654
<input autocomplete="off" class="is-invalid" disabled type="hidden">
1655-
<div class="invalid-feedback">Email is invalid</div>
1655+
<div class="invalid-feedback" id="user_email_feedback">Email is invalid</div>
16561656
</form>
16571657
```
16581658

@@ -1673,7 +1673,7 @@ Which outputs:
16731673
```html
16741674
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
16751675
<input autocomplete="off" class="is-invalid" disabled type="hidden">
1676-
<div class="invalid-feedback">is invalid</div>
1676+
<div class="invalid-feedback" id="user_email_feedback">is invalid</div>
16771677
</form>
16781678
```
16791679

@@ -1692,7 +1692,7 @@ Which outputs:
16921692
```html
16931693
<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post">
16941694
<input autocomplete="off" class="is-invalid" disabled type="hidden">
1695-
<div class="custom-error">Email is invalid</div>
1695+
<div class="custom-error" id="user_email_feedback">Email is invalid</div>
16961696
</form>
16971697
```
16981698

lib/bootstrap_form/components/labels.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def prepare_label_options(id, name, options, custom_label_col, group_layout)
5252

5353
options[:class] = label_classes(name, options, custom_label_col, group_layout)
5454
options.delete(:class) if options[:class].none?
55+
options[:id] = field_id(name, :feedback) if error?(name) && label_errors
5556
end
5657
end
5758
end

lib/bootstrap_form/components/validation.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def generate_error(name)
6868
help_klass = "invalid-feedback"
6969
help_tag = :div
7070

71-
content_tag(help_tag, help_text, class: help_klass)
71+
content_tag(help_tag, help_text, class: help_klass, id: field_id(name, :feedback))
7272
end
7373

7474
def get_error_messages(name)

lib/bootstrap_form/form_group_builder.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,10 @@ def form_group_css_options(method, html_options, options)
9898
# Add control_class; allow it to be overridden by :control_class option
9999
control_classes = css_options.delete(:control_class) { control_class }
100100
css_options[:class] = safe_join([control_classes, css_options[:class]].compact, " ")
101-
css_options[:class] << " is-invalid" if error?(method)
101+
if error?(method)
102+
css_options[:class] << " is-invalid"
103+
css_options[:aria] = { labelledby: field_id(method, :feedback) }
104+
end
102105
css_options[:placeholder] = form_group_placeholder(options, method) if options[:label_as_placeholder]
103106
css_options
104107
end

lib/bootstrap_form/helpers/bootstrap.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def errors_on(name, options={})
3434
hide_attribute_name = options[:hide_attribute_name] || false
3535
custom_class = options[:custom_class] || false
3636

37-
tag.div class: custom_class || "invalid-feedback" do
37+
tag.div(class: custom_class || "invalid-feedback", id: field_id(name, :feedback)) do
3838
errors = if hide_attribute_name
3939
object.errors[name]
4040
else

lib/bootstrap_form/inputs/check_box.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def check_box_options(name, options)
4141
:inline, :label, :label_class, :label_col, :layout, :skip_label,
4242
:switch, :wrapper, :wrapper_class)
4343
check_box_options[:class] = check_box_classes(name, options)
44+
check_box_options[:aria] = { labelledby: field_id(name, :feedback) } if error?(name)
4445
check_box_options.merge!(required_field_options(options, name))
4546
end
4647

lib/bootstrap_form/inputs/radio_button.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def radio_button_options(name, options)
2828
radio_button_options = options.except(:class, :label, :label_class, :error_message, :help,
2929
:inline, :hide_label, :skip_label, :wrapper, :wrapper_class)
3030
radio_button_options[:class] = radio_button_classes(name, options)
31+
radio_button_options[:aria] = { labelledby: field_id(name, :feedback) } if error?(name)
3132
radio_button_options.merge!(required_field_options(options, name))
3233
end
3334

test/bootstrap_form_test.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -807,7 +807,9 @@ def warn(message, ...)
807807
@user.email = nil
808808
assert @user.invalid?
809809

810-
expected = '<div class="invalid-feedback" id="user_email_feedback">can\'t be blank, is too short (minimum is 5 characters)</div>'
810+
expected = <<~HTML
811+
<div class="invalid-feedback" id="user_email_feedback">can't be blank, is too short (minimum is 5 characters)</div>
812+
HTML
811813

812814
assert_equivalent_html expected, @builder.errors_on(:email, hide_attribute_name: true)
813815
end
@@ -816,7 +818,11 @@ def warn(message, ...)
816818
@user.email = nil
817819
assert @user.invalid?
818820

819-
expected = '<div class="custom-error-class" id="user_email_feedback">Email can\'t be blank, Email is too short (minimum is 5 characters)</div>'
821+
expected = <<~HTML
822+
<div class="custom-error-class" id="user_email_feedback">
823+
Email can't be blank, Email is too short (minimum is 5 characters)
824+
</div>
825+
HTML
820826

821827
assert_equivalent_html expected, @builder.errors_on(:email, custom_class: "custom-error-class")
822828
end

0 commit comments

Comments
 (0)