diff --git a/lib/bootstrap_form/form_builder.rb b/lib/bootstrap_form/form_builder.rb index bcc70c66d..13b791dae 100644 --- a/lib/bootstrap_form/form_builder.rb +++ b/lib/bootstrap_form/form_builder.rb @@ -38,9 +38,7 @@ def initialize(object_name, object, template, options) define_method(with_method_name) do |name, options = {}| form_group_builder(name, options) do - prepend_and_append_input(options) do - send(without_method_name, name, options) - end + send(without_method_name, name, options) end end @@ -52,6 +50,7 @@ def initialize(object_name, object, template, options) without_method_name = "#{method_name}_without_bootstrap" define_method(with_method_name) do |name, options = {}, html_options = {}| + prevent_prepend_and_append!(options) form_group_builder(name, options, html_options) do content_tag(:div, send(without_method_name, name, options, html_options), class: control_specific_class(method_name)) end @@ -61,6 +60,7 @@ def initialize(object_name, object, template, options) end def file_field_with_bootstrap(name, options = {}) + prevent_prepend_and_append!(options) options = options.reverse_merge(control_class: 'form-control-file') form_group_builder(name, options) do file_field_without_bootstrap(name, options) @@ -71,15 +71,14 @@ def file_field_with_bootstrap(name, options = {}) def select_with_bootstrap(method, choices = nil, options = {}, html_options = {}, &block) form_group_builder(method, options, html_options) do - prepend_and_append_input(options) do - select_without_bootstrap(method, choices, options, html_options, &block) - end + select_without_bootstrap(method, choices, options, html_options, &block) end end bootstrap_method_alias :select def collection_select_with_bootstrap(method, collection, value_method, text_method, options = {}, html_options = {}) + prevent_prepend_and_append!(options) form_group_builder(method, options, html_options) do collection_select_without_bootstrap(method, collection, value_method, text_method, options, html_options) end @@ -88,6 +87,7 @@ def collection_select_with_bootstrap(method, collection, value_method, text_meth bootstrap_method_alias :collection_select def grouped_collection_select_with_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) + prevent_prepend_and_append!(options) form_group_builder(method, options, html_options) do grouped_collection_select_without_bootstrap(method, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options) end @@ -96,6 +96,7 @@ def grouped_collection_select_with_bootstrap(method, collection, group_method, g bootstrap_method_alias :grouped_collection_select def time_zone_select_with_bootstrap(method, priority_zones = nil, options = {}, html_options = {}) + prevent_prepend_and_append!(options) form_group_builder(method, options, html_options) do time_zone_select_without_bootstrap(method, priority_zones, options, html_options) end @@ -104,6 +105,7 @@ def time_zone_select_with_bootstrap(method, priority_zones = nil, options = {}, bootstrap_method_alias :time_zone_select def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_value = "0", &block) + prevent_prepend_and_append!(options) options = options.symbolize_keys! check_box_options = options.except(:label, :label_class, :help, :inline, :custom, :hide_label, :skip_label) check_box_classes = [check_box_options[:class]] @@ -164,6 +166,7 @@ def check_box_with_bootstrap(name, options = {}, checked_value = "1", unchecked_ bootstrap_method_alias :check_box def radio_button_with_bootstrap(name, value, *args) + prevent_prepend_and_append!(options) options = args.extract_options!.symbolize_keys! radio_options = options.except(:label, :label_class, :help, :inline, :custom, :hide_label, :skip_label) radio_classes = [options[:class]] @@ -210,6 +213,7 @@ def radio_button_with_bootstrap(name, value, *args) bootstrap_method_alias :radio_button def collection_check_boxes_with_bootstrap(*args) + prevent_prepend_and_append!(options) html = inputs_collection(*args) do |name, value, options| options[:multiple] = true check_box(name, options, value, nil) @@ -220,6 +224,7 @@ def collection_check_boxes_with_bootstrap(*args) bootstrap_method_alias :collection_check_boxes def collection_radio_buttons_with_bootstrap(*args) + prevent_prepend_and_append!(options) inputs_collection(*args) do |name, value, options| radio_button(name, value, options) end @@ -235,10 +240,9 @@ def form_group(*args, &block) options[:class] << " row" if get_group_layout(options[:layout]) == :horizontal options[:class] << " #{feedback_class}" if options[:icon] - content_tag(:div, options.except(:id, :label, :help, :icon, :label_col, :control_col, :layout)) do + content_tag(:div, options.except(:append, :id, :label, :help, :icon, :input_group_class, :label_col, :control_col, :layout, :prepend)) do 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 = prepend_and_append_input(name, options, &block).to_s if get_group_layout(options[:layout]) == :horizontal control_class = options[:control_col] || control_col @@ -366,6 +370,10 @@ def form_group_builder(method, options, html_options = nil) class: wrapper_class } + form_group_options[:append] = options.delete(:append) if options[:append] + form_group_options[:prepend] = options.delete(:prepend) if options[:prepend] + form_group_options[:input_group_class] = options.delete(:input_group_class) if options[:input_group_class] + if wrapper_options.is_a?(Hash) form_group_options.merge!(wrapper_options) end diff --git a/lib/bootstrap_form/helpers/bootstrap.rb b/lib/bootstrap_form/helpers/bootstrap.rb index 058c9dc05..f8fcd23a7 100644 --- a/lib/bootstrap_form/helpers/bootstrap.rb +++ b/lib/bootstrap_form/helpers/bootstrap.rb @@ -66,18 +66,28 @@ def custom_control(*args, &block) form_group_builder(name, options, &block) end - def prepend_and_append_input(options, &block) + def prepend_and_append_input(name, options, &block) + help = options[:help] options = options.extract!(:prepend, :append, :input_group_class) input_group_class = ["input-group", options[:input_group_class]].compact.join(' ') - input = capture(&block) + input = capture(&block) || "".html_safe input = content_tag(:div, input_group_content(options[:prepend]), class: 'input-group-prepend') + input if options[:prepend] input << content_tag(:div, input_group_content(options[:append]), class: 'input-group-append') if options[:append] + input << generate_help(name, help).to_s input = content_tag(:div, input, class: input_group_class) unless options.empty? input end + # Some helpers don't currently accept prepend and append. However, it's not + # clear if that's corrent. In the meantime, strip to options before calling + # methods that don't accept prepend and append. + def prevent_prepend_and_append!(options) + options.delete(:append) + options.delete(:prepend) + end + def input_group_content(content) return content if content.match(/btn/) content_tag(:span, content, class: 'input-group-text') diff --git a/test/bootstrap_form_group_test.rb b/test/bootstrap_form_group_test.rb index 9f0714802..11bfa46d0 100644 --- a/test/bootstrap_form_group_test.rb +++ b/test/bootstrap_form_group_test.rb @@ -147,6 +147,31 @@ class BootstrapFormGroupTest < ActionView::TestCase assert_equivalent_xml expected, @builder.text_field(:email, prepend: '$', append: '.00') end + test "adding both prepend and append text with validation error" do + @user.email = nil + assert @user.invalid? + + expected = <<-HTML.strip_heredoc +
+ +
+ +
+
+ $
+
+ +
+ .00 +
+
can't be blank, is too short (minimum is 5 characters) +
+
+
+ HTML + assert_equivalent_xml expected, bootstrap_form_for(@user) { |f| f.text_field :email, prepend: '$', append: '.00' } + end + test "help messages for default forms" do expected = <<-HTML.strip_heredoc