Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Twitter Bootstrap Form Builder
class BootstrapFormBuilder < ActionView::Helpers::FormBuilder
delegate :capture, :content_tag, :tag, to: :@template
%w[text_field text_area password_field collection_select].each do |method_name|
define_method(method_name) do |name, *args|
errors = object.errors[name].any?? " error" : ""
error_msg = object.errors[name].any?? content_tag(:span, object.errors[name].join(","), class: "help-inline") : ""
content_tag :div, class: "clearfix#{errors}" do
field_label(name, *args) + content_tag(:div, class: "input#{errors}") do
super(name, *args) + " " + error_msg
end
end
end
end
def check_box(name, *args)
content_tag :div, class: "clearfix" do
content_tag(:div, class:"input") do
content_tag(:ul, class:"inputs-list") do
content_tag(:li) do
content_tag(:label) do
super(name, *args) + content_tag(:span) do
field_label(name, *args)
end
end
end
end
end
end
end
def div(*args, &block)
options = args.extract_options!
data = block_given? ? capture(&block) : ''
content_tag(:div, data, class: options[:class])
end
def submit(*args)
super(*args, class: "btn primary")
end
private
def field_label(name, *args)
options = args.extract_options!
required = object.class.validators_on(name).any? { |v| v.kind_of? ActiveModel::Validations::PresenceValidator}
label(name, options[:label], class: ("required" if required))
end
def objectify_options(options)
super.except(:label)
end
end
<%= bootstrap_form_for @project do |f| %>
<%= f.text_field :name, class: "span7" %>
<%= f.text_area :description, rows: 8, class: "span7" %>
<%= f.check_box :active %>
<%= f.div class: "actions" do %>
<%= f.submit %>
<%= link_to "Cancel", projects_path, class: "btn danger" %>
<% end %>
<% end %>
@danneu

This comment has been minimized.

Copy link

danneu commented Jan 1, 2012

Ternary operations are easier to read when you isolate the "?".

Ex:

errors = object.errors[name].any? ? " error" : ""

Thanks for sharing. This is exactly what I was going to do after I watched that Railscast.

@cbmeeks

This comment has been minimized.

Copy link
Owner Author

cbmeeks commented Jan 1, 2012

Yeah, that's true. For some reason, I was thinking of ?? as a real question. lol

Glad I helped you out.

@SathishRaju

This comment has been minimized.

Copy link

SathishRaju commented Jan 7, 2012

Modified your method to add the help text also:

 %w[text_field text_area password_field collection_select].each do |method_name|
    define_method(method_name) do |name, *args|
      errors = object.errors[name].any? ? " error" : ""
      error_msg = object.errors[name].any? ? content_tag(:span, object.errors[name].join(","), class: "help-inline") : ""
      options = args.extract_options!
      help_text =  !options[:help_text].blank? ? content_tag(:span,options[:help_text], class: "help-block") : "" 
      content_tag :div, class: "clearfix#{errors}" do
        field_label(name, *args) + content_tag(:div, class: "input#{errors}") do
          super(name, *args) + " " + error_msg 
        end   +  help_text 
        
      end
      
    end
  end

Then you can pass help text as follows:

 f.text_area :tags, rows: 8, class: "span7", help_text: 'Please enter meaningful tags'
@SathishRaju

This comment has been minimized.

Copy link

SathishRaju commented Jan 7, 2012

small correction, after extracting the options, you have to push it back again. Otherwise the options will not be passed .

 %w[text_field text_area password_field collection_select].each do |method_name|
    define_method(method_name) do |name, *args|
      errors = object.errors[name].any? ? " error" : ""
      error_msg = object.errors[name].any? ? content_tag(:span, object.errors[name].join(","), class: "help-inline") : ""
      options = args.extract_options!
      help_text =  !options[:help_text].blank? ? content_tag(:span,options[:help_text], class: "help-block") : ""
      args.push(options)
      content_tag :div, class: "clearfix#{errors}" do
        field_label(name, *args) + content_tag(:div, class: "input#{errors}") do
          super(name, *args) + " " + error_msg 
        end  +  help_text
        
      end
      
    end
  end
@danneu

This comment has been minimized.

Copy link

danneu commented Jan 7, 2012

heh, is there an extract_options without the destructive !?

@SathishRaju

This comment has been minimized.

Copy link

SathishRaju commented Jan 7, 2012

@cbmeeks

This comment has been minimized.

Copy link
Owner Author

cbmeeks commented Jan 7, 2012

I tried your changes but it totally screwed up the forms. All of the styling went away. Then I changed the *args to options like so and it works. However, the help_text is left justified and not in alignment with the forms.

@cbmeeks

This comment has been minimized.

Copy link
Owner Author

cbmeeks commented Jan 7, 2012

class BootstrapFormBuilder < ActionView::Helpers::FormBuilder

  delegate :capture, :content_tag, :tag, to: :@template

  %w[text_field text_area password_field collection_select].each do |method_name|
    define_method(method_name) do |name, *args|
      errors = object.errors[name].any?? " error" : ""
      error_msg = object.errors[name].any?? content_tag(:span, object.errors[name].join(","), class: "help-inline") : ""
      options = args.extract_options!
      help_text =  !options[:help_text].blank? ? content_tag(:span,options[:help_text], class: "help-block") : "" 
      content_tag :div, class: "clearfix#{errors}" do
        field_label(name, options) + content_tag(:div, class: "input#{errors}") do
          super(name, options) + " " + error_msg
        end + help_text
      end
    end
  end

  def check_box(name, *args)
    content_tag :div, class: "clearfix" do
      content_tag(:div, class:"input") do
        content_tag(:ul, class:"inputs-list") do
          content_tag(:li) do
            content_tag(:label) do
              super(name, *args) + content_tag(:span) do
                field_label(name, *args)
              end
            end
          end
        end
      end
    end
  end

  def submit(*args)
    super(*args, class: "btn primary")
  end

private

  def field_label(name, *args)
    options = args.extract_options!
    required = object.class.validators_on(name).any? { |v| v.kind_of? ActiveModel::Validations::PresenceValidator}
    label(name, options[:label], class: ("required" if required))
  end

  def objectify_options(options)
    super.except(:label)
  end

end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.