VegerWeb logo

Simple form with Bootstrap input groups

Blog post header showing a down-down login box that is properly formatted

I was looking to have an easy way to format its forms for this website, without requiring to manually fiddling with CSS classes. After some looking around, the simple_form Ruby gem looked promising and is supporting Bootstrap, so I decided to use it. All fine so far: forms are nicely formatted with no formatting code in the views. But when I decided to use Bootstrap input groups to get a mobile-friendly experience, for the login drop-down form at the top right of the page, simple_form did not play along nicely. It proved (virtually) impossible to get the formatting right without manually formatting the form:

Garbled Bootstrap login form

This example is rendered using the following view code as simple_form is intended to be used:

<%= f.input :login do %>
  <span class="input-group-addon"><%= icon 'user' %></span>
  <%= f.input :login %>
<% end %>

The main problem is that both the input group and the input form field are contained in a <div>-element with the same CSS classes:

<div class="form-group string optional user_login">
  <div class="input-group">
    <span class="input-group-addon"><i class="fa fa-user"></i></span>
    <div class="form-group string optional user_login">
      <div class="input-group">
        <input class="form-control string optional" placeholder="Login" type="text" name="user[login]" id="user_login">
      </div>
    </div>
  </div>
</div>

This is not how Bootstrap needs the formatting of the field. The only way to tell simple_form to drop the extra container, I could think of, is to use an input_field instead of input. An input_field is not processed by simple_form so not additional container is added around the actual form field:

Bootstrap field without right-side formatting

The style of the right side of the (actual) input field is unfortunately incorrect, no nice rounded border for example. This is because input_field is not being processed by simple_form anymore, so its required class input-group is not automatically added. This can be solved by adding the class manually in the view:

<%= f.input :login do %>
  <span class="input-group-addon"><%= icon 'user' %></span>
  <%= f.input :login, class: "form-control" %>
<% end %>

I have been trying for hours to get a combination of wrappers and field types in order to fix this issue, but this is the best I could come up with. It has minimal manual modifications, but unfortunately not zero. Since simple_form is new for me, I might have been overlooking some configuration, wrapper type, or possibility. If you are more experienced with simple_form or got better luck in figuring this last manual step out, please drop a note in the comments or use the contact form.

For completeness sake, the simple_form wrapper I use is as follows:

config.wrappers :vertical_input_group, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
  b.use :html5
  b.use :placeholder

  b.wrapper tag: 'div', class: 'input-group ' do |append|
    append.use :input, class: 'form-control'
  end
  b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
  b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
end