Skip to content

Commit 7305528

Browse files
committed
Merge pull request bootstrap-ruby#150 from krsyoung/required_label_asterix
Required label asterix
2 parents b4bd8c6 + af28315 commit 7305528

File tree

7 files changed

+61
-26
lines changed

7 files changed

+61
-26
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ Features:
3838
- Added the ability to pass any attributes to wrapper (#136, @atipugin)
3939
- Split monolithic test file into several smaller files (#141, @spacewander)
4040
- Added role="form" attribute to forms (#142, @spacewander)
41+
- Allow users to display validation errors in labels (#144, @timcheadle)
42+
- Use #underscore, not #downcase for help text scope (#140, @atipugin)
43+
- Added a `required` CSS class for labels with required attributes (#150, @krsyoung)
4144

4245
## 2.1.1 (2014-04-20)
4346

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,23 @@ class, which keeps your labels accessible to those using screen readers.
133133
```erb
134134
<%= f.text_area :comment, hide_label: :true, placeholder: "Leave a comment..." %>
135135
```
136+
#### Required Fields
137+
138+
A label that is associated with a required field is automatically annotated with
139+
a `required` CSS class. You are free to add any appropriate CSS to style
140+
required fields as desired. One example would be to automatically add an
141+
asterisk to the end of the label:
142+
143+
```css
144+
label.required:after {
145+
content:" *";
146+
}
147+
```
148+
149+
The label `required` class is determined based on the definition of a presence
150+
validator with the associated model attribute. Presently this is one of:
151+
ActiveRecord::Validations::PresenceValidator or
152+
ActiveModel::Validations::PresenceValidator.
136153

137154
### Help Text
138155

@@ -152,7 +169,7 @@ en:
152169
password: "A good password should be at least six characters long"
153170
```
154171
155-
If your model name has multiple words (like `SuperUser`), the key on the
172+
If your model name has multiple words (like `SuperUser`), the key on the
156173
translation file should be underscored (`super_user`).
157174

158175
You can override help translations for a particular field by passing the `help`

lib/bootstrap_form/form_builder.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,18 @@ def has_error?(name)
253253
object.respond_to?(:errors) && !(name.nil? || object.errors[name].empty?)
254254
end
255255

256+
def required_attribute?(obj, attribute)
257+
258+
return false unless obj and attribute
259+
260+
target = (obj.class == Class) ? obj : obj.class
261+
target_validators = target.validators_on(attribute).map(&:class)
262+
target_validators.include?(
263+
ActiveRecord::Validations::PresenceValidator) ||
264+
target_validators.include?(
265+
ActiveModel::Validations::PresenceValidator)
266+
end
267+
256268
def form_group_builder(method, options, html_options = nil)
257269
options.symbolize_keys!
258270
html_options.symbolize_keys! if html_options
@@ -309,6 +321,8 @@ def generate_label(id, name, options, custom_label_col, group_layout)
309321
options[:for] = id if acts_like_form_tag
310322
classes = [options[:class], label_class]
311323
classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
324+
classes << "required" if required_attribute?(object, name)
325+
312326
options[:class] = classes.compact.join(" ")
313327

314328
if label_errors && has_error?(name)
@@ -318,6 +332,7 @@ def generate_label(id, name, options, custom_label_col, group_layout)
318332
else
319333
label(name, options[:text], options.except(:text))
320334
end
335+
321336
end
322337

323338
def generate_help(name, help_text)

test/bootstrap_fields_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def setup
7979
end
8080

8181
test "text fields are wrapped correctly" do
82-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
82+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
8383
assert_equal expected, @builder.text_field(:email)
8484
end
8585

test/bootstrap_form_group_test.rb

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ def setup
88
end
99

1010
test "changing the label text" do
11-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email Address</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
11+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email Address</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
1212
assert_equal expected, @builder.text_field(:email, label: 'Email Address')
1313
end
1414

1515
test "hiding a label" do
16-
expected = %{<div class="form-group"><label class="sr-only control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
16+
expected = %{<div class="form-group"><label class="sr-only control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
1717
assert_equal expected, @builder.text_field(:email, hide_label: true)
1818
end
1919

@@ -23,17 +23,17 @@ def setup
2323
end
2424

2525
test "adding prepend text" do
26-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><div class="input-group"><span class="input-group-addon">@</span><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div></div>}
26+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><div class="input-group"><span class="input-group-addon">@</span><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div></div>}
2727
assert_equal expected, @builder.text_field(:email, prepend: '@')
2828
end
2929

3030
test "adding append text" do
31-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><div class="input-group"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="input-group-addon">.00</span></div></div>}
31+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><div class="input-group"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="input-group-addon">.00</span></div></div>}
3232
assert_equal expected, @builder.text_field(:email, append: '.00')
3333
end
3434

3535
test "append and prepend button" do
36-
prefix = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><div class="input-group">}
36+
prefix = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><div class="input-group">}
3737
field = %{<input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" />}
3838
button = %{<span class="input-group-btn"><a class="btn btn-default" href="#">Click</a></span>}
3939
suffix = %{</div></div>}
@@ -47,17 +47,17 @@ def setup
4747
end
4848

4949
test "adding both prepend and append text" do
50-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><div class="input-group"><span class="input-group-addon">$</span><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="input-group-addon">.00</span></div></div>}
50+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><div class="input-group"><span class="input-group-addon">$</span><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="input-group-addon">.00</span></div></div>}
5151
assert_equal expected, @builder.text_field(:email, prepend: '$', append: '.00')
5252
end
5353

5454
test "help messages for default forms" do
55-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="help-block">This is required</span></div>}
55+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="help-block">This is required</span></div>}
5656
assert_equal expected, @builder.text_field(:email, help: 'This is required')
5757
end
5858

5959
test "help messages for horizontal forms" do
60-
expected = %{<div class="form-group"><label class="control-label col-sm-2" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="help-block">This is required</span></div></div>}
60+
expected = %{<div class="form-group"><label class="control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /><span class="help-block">This is required</span></div></div>}
6161
assert_equal expected, @horizontal_builder.text_field(:email, help: "This is required")
6262
end
6363

@@ -112,7 +112,7 @@ def setup
112112
%{<p class="form-control-static">Bar</p>}.html_safe
113113
end
114114

115-
expected = %{<div class="form-group"><label class="control-label col-sm-2" for="user_email">Custom Control</label><div class="col-sm-10"><p class="form-control-static">Bar</p></div></div>}
115+
expected = %{<div class="form-group"><label class="control-label col-sm-2 required" for="user_email">Custom Control</label><div class="col-sm-10"><p class="form-control-static">Bar</p></div></div>}
116116
assert_equal expected, output
117117
end
118118

@@ -164,7 +164,7 @@ def setup
164164
@user.email = nil
165165
@user.valid?
166166

167-
expected = %{<div class="form-group none-margin has-error"><div class="field_with_errors"><label class="control-label" for="user_email">Email</label></div><div class="field_with_errors"><input class="form-control" id="user_email" name="user[email]" type="email" /></div><span class="help-block">can&#39;t be blank, is too short (minimum is 5 characters)</span></div>}
167+
expected = %{<div class="form-group none-margin has-error"><div class="field_with_errors"><label class="control-label required" for="user_email">Email</label></div><div class="field_with_errors"><input class="form-control" id="user_email" name="user[email]" type="email" /></div><span class="help-block">can&#39;t be blank, is too short (minimum is 5 characters)</span></div>}
168168
assert_equal expected, @builder.email_field(:email, wrapper_class: 'none-margin')
169169
end
170170

@@ -176,7 +176,7 @@ def setup
176176
f.text_field(:email, help: 'This is required', wrapper_class: 'none-margin')
177177
end
178178

179-
expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group none-margin has-error"><label class="control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" /><span class="help-block">can&#39;t be blank, is too short (minimum is 5 characters)</span></div></form>}
179+
expected = %{<form accept-charset="UTF-8" action="/users" class="new_user" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group none-margin has-error"><label class="control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="text" /><span class="help-block">can&#39;t be blank, is too short (minimum is 5 characters)</span></div></form>}
180180
assert_equal expected, output
181181
end
182182

@@ -211,7 +211,7 @@ def setup
211211

212212
output = output + @horizontal_builder.text_field(:email)
213213

214-
expected = %{<div class="form-group"><div class="col-sm-10 col-sm-offset-2">Hallo</div></div><div class="form-group"><label class="control-label col-sm-2" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div></div>}
214+
expected = %{<div class="form-group"><div class="col-sm-10 col-sm-offset-2">Hallo</div></div><div class="form-group"><label class="control-label col-sm-2 required" for="user_email">Email</label><div class="col-sm-10"><input class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div></div>}
215215
assert_equal expected, output
216216
end
217217

@@ -221,7 +221,7 @@ def setup
221221
end
222222

223223
test "passing options to a form control get passed through" do
224-
expected = %{<div class="form-group"><label class="control-label" for="user_email">Email</label><input autofocus="autofocus" class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
224+
expected = %{<div class="form-group"><label class="control-label required" for="user_email">Email</label><input autofocus="autofocus" class="form-control" id="user_email" name="user[email]" type="text" value="steve@example.com" /></div>}
225225
assert_equal expected, @builder.text_field(:email, autofocus: true)
226226
end
227227

@@ -235,7 +235,7 @@ def setup
235235
end
236236

237237
test "custom form group layout option" do
238-
expected = %{<form accept-charset="UTF-8" action="/users" class="form-horizontal" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="control-label" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></form>}
238+
expected = %{<form accept-charset="UTF-8" action="/users" class="form-horizontal" id="new_user" method="post" role="form"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /></div><div class="form-group"><label class="control-label required" for="user_email">Email</label><input class="form-control" id="user_email" name="user[email]" type="email" value="steve@example.com" /></div></form>}
239239
assert_equal expected, bootstrap_form_for(@user, layout: :horizontal) { |f| f.email_field :email, layout: :inline }
240240
end
241241
end

0 commit comments

Comments
 (0)