diff --git a/README.md b/README.md index c1404a130..d207e64df 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,16 @@ If your form is not backed by a model, use the `bootstrap_form_tag`. Usage of th <% end %> ``` +### bootstrap_form_with + +If you are using Rails >= 5.1 just use the `bootstrap_form_with` helper. Here's an example: + +```erb +<%= bootstrap_form_with(model: @user) do |f| %> + <%= f.email_field :email %> +<% end %> +``` + ## Form Helpers This gem wraps the following Rails form helpers: diff --git a/lib/bootstrap_form/helper.rb b/lib/bootstrap_form/helper.rb index ee73c9016..ed7e5d6c2 100644 --- a/lib/bootstrap_form/helper.rb +++ b/lib/bootstrap_form/helper.rb @@ -39,5 +39,29 @@ def temporarily_disable_field_error_proc ensure ActionView::Base.field_error_proc = original_proc end + + if ::Rails::VERSION::STRING >= '5.1' + def bootstrap_form_with(options = {}, &block) + options.reverse_merge!({builder: BootstrapForm::FormBuilder}) + + options[:html] ||= {} + options[:html][:role] ||= 'form' + + layout = case options[:layout] + when :inline + "form-inline" + when :horizontal + "form-horizontal" + end + + if layout + options[:html][:class] = [options[:html][:class], layout].compact.join(" ") + end + + temporarily_disable_field_error_proc do + form_with(options, &block) + end + end + end end end diff --git a/test/bootstrap_form_with_test.rb b/test/bootstrap_form_with_test.rb new file mode 100644 index 000000000..98d0ebd35 --- /dev/null +++ b/test/bootstrap_form_with_test.rb @@ -0,0 +1,139 @@ +require 'test_helper' + +if ::Rails::VERSION::STRING >= '5.1' + class BootstrapFormWithTest < ActionView::TestCase + include BootstrapForm::Helper + + def setup + setup_test_fixture + end + + test "default-style forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user) { |f| nil } + end + + test "inline-style forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :inline) { |f| nil } + end + + test "horizontal-style forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal) { |f| f.email_field :email } + end + + test "existing styles aren't clobbered when specifying a form style" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal, html: { class: "my-style" }) { |f| f.email_field :email } + end + + test "given role attribute should not be covered by default role attribute" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, html: { role: 'not-a-form'}) {|f| nil} + 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 = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @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 = %{
can't be blank, is too short (minimum is 5 characters)
ost\" role=\"form\">
can't be blank, is too short (minimum is 5 characters)
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, label_errors: true, inline_errors: true) { |f| f.text_field :email } + end + + test "label error messages use humanized attribute names" do + I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: 'Your e-mail address'}}}}) + + @user.email = nil + @user.valid? + + expected = %{
can't be blank, is too short (minimum is 5 characters)
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, label_errors: true, inline_errors: true) { |f| f.text_field :email } + + I18n.backend.store_translations(:en, {activerecord: {attributes: {user: {email: nil}}}}) + end + + test "alert_message contains the error summary when inline_errors are turned off" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: false) do |f| + f.alert_message('Please fix the following errors:') + end + + expected = %{

Please fix the following errors:

} + assert_equivalent_xml expected, output + end + + test "alert_message allows the error_summary to be turned off" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: false) do |f| + f.alert_message('Please fix the following errors:', error_summary: false) + end + + expected = %{

Please fix the following errors:

} + assert_equivalent_xml expected, output + end + + test "alert_message allows the error_summary to be turned on with inline_errors also turned on" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: true) do |f| + f.alert_message('Please fix the following errors:', error_summary: true) + end + + expected = %{

Please fix the following errors:

} + assert_equivalent_xml expected, output + end + + test "custom label width for horizontal forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal) { |f| f.email_field :email, label_col: 'col-sm-1' } + end + + test "offset for form group without label respects label width for horizontal forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal, label_col: 'col-md-2', control_col: 'col-md-10') { |f| f.form_group { f.submit } } + end + + test "custom input width for horizontal forms" do + expected = %{
} + assert_equivalent_xml expected, bootstrap_form_with(model: @user, layout: :horizontal) { |f| f.email_field :email, control_col: 'col-sm-5' } + end + + test "the field contains the error and is not wrapped in div.field_with_errors when bootstrap_form_with is used" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user) do |f| + f.text_field(:email, help: 'This is required') + end + + expected = %{
can't be blank, is too short (minimum is 5 characters)
} + assert_equivalent_xml expected, output + end + + test "help is preserved when inline_errors: false is passed to bootstrap_form_with" do + @user.email = nil + @user.valid? + + output = bootstrap_form_with(model: @user, inline_errors: false) do |f| + f.text_field(:email, help: 'This is required') + end + + expected = %{
This is required
} + assert_equivalent_xml expected, output + end + end +end