Reputation: 269
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?
Upvotes: 6
Views: 8865
Reputation: 346
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
Upvotes: 4
Reputation: 7339
The previous two answers will indeed work very well (simple form using your own initializer or use the bootstrap form gems). As with anything in code, there are many ways to skin a cat. Another (more manual) way is to add a form helper of your own. The steps are basically:
app/helpers/custom_form_helper.rb
CustomFormBuilder < ActionView::Helpers::FormBuilder
Create the look you want.
def text_field(label, *args)
options = args.extract_options!
new_class = options[:class] || "form-control"
super("dd", label, *(args << options.merge(:class => new_class)))
end
Call your helper method in application so you don not have to include the helper each time you call a form, like:
def custom_form_for(name, *args, &block)
options = args.extract_options!
content_tag("div",
content_tag("dl", form_for(name, *(args << options.merge(:builder => CustomFormBuilder)), &block)), :class => "standard_form")
end
Use the custom form in your forms as custom_form_for
Upvotes: 0
Reputation: 44880
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
Upvotes: 10
Reputation: 2125
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
Upvotes: 1
Reputation: 24815
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.
Upvotes: 1