Simple_form: how to change input's wrapper's class?(not the wrapper_html effect on)

PeterZD picture PeterZD · Sep 9, 2014 · Viewed 9.9k times · Source

I have a problem when using simple_form and Bootstrap 3. About the input's wrapper tag. Show codes below:

view code(with haml)

= simple_form_for @refer_email_form, url: create_refer_message_path, html: { class: "form-horizontal" } do |f|
  = f.input :to, label_html: { class: "col-sm-2" }
  = f.input :subject, label_html: { class: "col-sm-2" }

config/simple_form_bootstrap.rb

SimpleForm.setup do |config|
  config.input_class = "form-control"

  config.wrappers :bootstrap, tag: 'div', class: 'form-group', error_class: 'error' do |b|
    b.use :html5
    b.use :placeholder
    b.use :label, class: "control-label"
    # b.wrapper tag: 'div', class: "col-sm-6" do |ba|
    b.wrapper tag: 'div' do |ba|
      ba.use :input
      ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end

 config.default_wrapper = :bootstrap

I just want to use the "Horizontal form" by default

the generated html

...
\<div class="form-group string optional refer_email_form_to">
  <label class="string optional control-label col-sm-2" for="refer_email_form_to">To</label>
  <div>
    <input class="string optional form-control" id="refer_email_form_to"   name="refer_email_form[to]" type="text">
  </div>
</div>
...

What I want is to change the <div>'s class which just wrap the <input> element, something like this:

...
<div class="col-sm-6">
  <input class="string optional form-control" id="refer_email_form_to"   name="refer_email_form[to]" type="text">
<div>
...

I've read the README from simple_form's github page, and googled for this problem, I know I can achieve this by adding b.wrapper tag: 'div', class: "col-sm-6" do |ba| to the config/simple_form_bootstrap.rb file, but the real problem is that I may use different class for the div, maybe col-sm-9 in other form. And I tried the input_html, wrapper_html in the view, but the wrapper_html effects on the first <div class="form-group">, and input_html only effects on the <input> element

Is there any way to change the <input>'s wrapper <div> dynamically in the view ?

Answer

Hoa picture Hoa · Nov 19, 2014

Change

b.wrapper tag: 'div' do |ba|

to

b.wrapper :my_wrapper, tag: 'div' do |ba|

Set up the input field as follows

= f.input :to, label_html: { class: "col-sm-2" }, wrapper: :bootstrap, my_wrapper_html: { class: "css-class-name-goes-here" }

The generated HTML is

<div class="form-group string optional refer_email_form_to">
  <label class="string optional control-label col-sm-2" for="refer_email_form_to">To</label>
  <div class="css-class-name-goes-here">
    <input class="string optional form-control" id="refer_email_form_to"   name="refer_email_form[to]" type="text">
  </div>
</div>

Notes

  1. I have to explicitly specify the “bootstrap” wrapper to make it work. The following setting doesn't seem to take effect config.default_wrapper = :bootstrap
  2. It doesn't work when I name the wrapper bootstrap as you do. The setting works when I use a different name such as bootstrap_x. This might be my local problem so this is just for your information in case you run into the same problem.
  3. If you're curious where all the above comes from, check out simple_form README file, it's in the "The wrappers API" section.