Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get class="form-control" in input fields by default (Rails Form Helper + Bootstrap 3)

I'm converting my site to Twitter Bootstrap 3, and have run into what seems like silly problem, but I haven't been able to find an easy solution via google.

How do I get class="form-control" to be populated by default in the Rails Form Helper? I can only do it by typing it explicitly, this seems like a waste of time. (below)

It is required for bootstrap to style the input.

 <%= f.label :email %>                                     
 <%= f.text_field :email, class: "form-control" %>   

Am I naive to think that Rails should add this feature just because bootstrap implemented it?

like image 278
wiredin Avatar asked Sep 17 '13 03:09

wiredin


4 Answers

Yup, this can be done without changing the way you use the Rails form helpers. You can extend the form helpers to include the class name if it is not already included in the options.

Note: You will have to override each method in FormTagHelper that you want to augment. This only augments text_field_tag.

Add something like this to your ApplicationHelper:

module ApplicationHelper

  module BootstrapExtension
    FORM_CONTROL_CLASS = "form-control"

    # Override the 'text_field_tag' method defined in FormTagHelper[1]
    #
    # [1] https://github.com/rails/rails/blob/master/actionview/lib/action_view/helpers/form_tag_helper.rb
    def text_field_tag(name, value = nil, options = {})
      class_name = options[:class]
      if class_name.nil?
        # Add 'form-control' as the only class if no class was provided
        options[:class] = FORM_CONTROL_CLASS
      else
        # Add ' form-control' to the class if it doesn't already exist
        options[:class] << " #{FORM_CONTROL_CLASS}" if
          " #{class_name} ".index(" #{FORM_CONTROL_CLASS} ").nil?
      end

      # Call the original 'text_field_tag' method to do the real work
      super
    end
  end

  # Add the modified method to ApplicationHelper
  include BootstrapExtension

end
like image 172
Ross Allen Avatar answered Oct 05 '22 22:10

Ross Allen


To get the class added to all form elements, even if those form elements are generated by gems like simple_form, the modification has to be done on a higher-level class than the ApplicationController. The following snippet can be placed in an initializer to do just that:

require 'action_view/helpers/tags/base'
# Most input types need the form-control class on them.  This is the easiest way to get that into every form input
module BootstrapTag
  FORM_CONTROL_CLASS = 'form-control'
  def tag(name, options, *)
    options = add_bootstrap_class_to_options options, true if name.to_s == 'input'
    super
  end

  private

  def content_tag_string(name, content, options, *)
    options = add_bootstrap_class_to_options options if name.to_s.in? %w(select textarea)
    super
  end

  def add_bootstrap_class_to_options(options, check_type = false)
    options = {} if options.nil?
    options.stringify_keys!
    if !check_type || options['type'].to_s.in?(%w(text password number email))
      options['class'] = [] unless options.has_key? 'class'
      options['class'] << FORM_CONTROL_CLASS if options['class'].is_a?(Array) && !options['class'].include?(FORM_CONTROL_CLASS)
      options['class'] << " #{FORM_CONTROL_CLASS}" if options['class'].is_a?(String) && options['class'] !~ /\b#{FORM_CONTROL_CLASS}\b/
    end
    options
  end
end

ActionView::Helpers::Tags::Base.send :include, BootstrapTag
ActionView::Base.send :include, BootstrapTag
like image 20
Jason Rust Avatar answered Oct 05 '22 22:10

Jason Rust


Yes, it's a waste of time.

Use simple_form gem which integrate nicely with Bootstrap. You no longer need to write these.

After bundle, just run

rails generate simple_form:install --bootstrap

Then a simple_form initailizer will be added. You can further customize it in initializers/simple_form_bootstrap, though default is good enough.

All these helper classed will be generated automatically, as well as many other good stuff.

like image 45
Billy Chan Avatar answered Oct 05 '22 22:10

Billy Chan


You can use one of the Bootstrap related Gems such as this one:

https://github.com/stouset/twitter_bootstrap_form_for

or this one:

https://github.com/sethvargo/bootstrap_forms

like image 43
Rajesh Kolappakam Avatar answered Oct 05 '22 22:10

Rajesh Kolappakam