Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,26 @@ You can turn off inline errors for the entire form like this:
<% end %>
```

### Label Errors

You can also display validation errors in the field's label; just turn
on the `:label_errors` option. Here's an example:

```
<%= bootstrap_form_for(@user, label_errors: true) do |f| %>
...
<% end %>
```

By default, turning on `:label_errors` will also turn off
`:inline_errors`. If you want both turned on, you can do that too:

```
<%= bootstrap_form_for(@user, label_errors: true, inline_errors: true) do |f| %>
...
<% end %>
```

### Alert Messages

To display an error message with an error summary, you can use the
Expand Down
25 changes: 21 additions & 4 deletions lib/bootstrap_form/form_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module BootstrapForm
class FormBuilder < ActionView::Helpers::FormBuilder
include BootstrapForm::Helpers::Bootstrap

attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :acts_like_form_tag
attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors, :label_errors, :acts_like_form_tag

FIELD_HELPERS = %w{color_field date_field datetime_field datetime_local_field
email_field month_field number_field password_field phone_field
Expand All @@ -19,7 +19,12 @@ def initialize(object_name, object, template, options)
@layout = options[:layout]
@label_col = options[:label_col] || default_label_col
@control_col = options[:control_col] || default_control_col
@inline_errors = options[:inline_errors] != false
@label_errors = options[:label_errors] || false
@inline_errors = if options[:inline_errors].nil?
@label_errors != true
else
options[:inline_errors] != false
end
@acts_like_form_tag = options[:acts_like_form_tag]

super
Expand Down Expand Up @@ -164,7 +169,7 @@ def form_group(*args, &block)
options[:class] << " #{feedback_class}" if options[:icon]

content_tag(:div, options.except(:id, :label, :help, :icon, :label_col, :control_col, :layout)) do
label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
label = generate_label(options[:id], name, options[:label], options[:label_col], options[:layout]) if options[:label]
control = capture(&block).to_s
control.concat(generate_help(name, options[:help]).to_s)
control.concat(generate_icon(options[:icon])) if options[:icon]
Expand All @@ -188,6 +193,8 @@ def fields_for_with_bootstrap(record_name, record_object = nil, fields_options =
fields_options[:layout] ||= options[:layout]
fields_options[:label_col] = fields_options[:label_col].present? ? "#{fields_options[:label_col]} #{label_class}" : options[:label_col]
fields_options[:control_col] ||= options[:control_col]
fields_options[:inline_errors] ||= options[:inline_errors]
fields_options[:label_errors] ||= options[:label_errors]
fields_for_without_bootstrap(record_name, record_object, fields_options, &block)
end

Expand Down Expand Up @@ -298,7 +305,13 @@ def generate_label(id, name, options, custom_label_col, group_layout)
classes << (custom_label_col || label_col) if get_group_layout(group_layout) == :horizontal
options[:class] = classes.compact.join(" ")

label(name, options[:text], options.except(:text))
if label_errors && has_error?(name)
error_messages = get_error_messages(name)
label_text = (options[:text] || name.to_s.humanize).to_s.concat(" #{error_messages}")
label(name, label_text, options.except(:text))
else
label(name, options[:text], options.except(:text))
end
end

def generate_help(name, help_text)
Expand All @@ -313,6 +326,10 @@ def generate_icon(icon)
content_tag(:span, "", class: "glyphicon glyphicon-#{icon} form-control-feedback")
end

def get_error_messages(name)
object.errors[name].join(", ")
end

def inputs_collection(name, collection, value, text, options = {}, &block)
form_group_builder(name, options) do
inputs = ""
Expand Down
16 changes: 16 additions & 0 deletions test/bootstrap_form_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ def setup
assert_equal expected, bootstrap_form_tag(url: '/users') { |f| f.check_box :misc }
end

test "errors display correctly and inline_errors are turned off by default when label_errors is true" do
@user.email = nil
@user.valid?

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 has-error\"><label class=\"control-label\" for=\"user_email\">Email can&#39;t be blank, is too short (minimum is 5 characters)</label><input class=\"form-control\" id=\"user_email\" name=\"user[email]\" type=\"text\" /></div></form>}
assert_equal expected, bootstrap_form_for(@user, label_errors: true) { |f| f.text_field :email }
end

test "errors display correctly and inline_errors can also be on when label_errors is true" do
@user.email = nil
@user.valid?

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 has-error\"><label class=\"control-label\" for=\"user_email\">Email can&#39;t be blank, is too short (minimum is 5 characters)</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>}
assert_equal expected, bootstrap_form_for(@user, label_errors: true, inline_errors: true) { |f| f.text_field :email }
end

test "alert message is wrapped correctly" do
@user.email = nil
@user.valid?
Expand Down