I'm using Twitter's Bootstrap toolkit for the layout in a proof of concept application I'm working on. So far my general impression is that I really like Bootstrap but there are a few obstacles to making it play nice with Rails.
One of those obstacles is that Rails formats fields with errors quite a bit differently than Bootstrap's CSS expects. Below I describe a possible solution. I'm not 100% sure this is the best approach but it seems to work well and I'm currently working on a proof of concept app that will be thrown out in several weeks so there's little risk if I'm wrong.
Rails default formatting looks like this...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- without error --> | |
<div class="clearfix"> | |
<label for="bar">Bar</label> | |
<div class="input"> | |
<input id="foo_bar" name="foo[bar]" size="30" type="text"> | |
</div> | |
</div> | |
<!-- with error --> | |
<div class="field"> | |
<div class="field_with_errors"> | |
<label for="foo_bar">Bar</label> | |
</div><br> | |
<div class="field_with_errors"> | |
<input id="foo_bar" name="foo[bar]" size="30" value="" type="text"> | |
</div> | |
</div> |
Bootstrap's CSS expects this....
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- without error --> | |
<div class="clearfix"> | |
<label for="bar">Bar</label> | |
<div class="input"> | |
<input id="foo_bar" name="foo[bar]" size="30" type="text"> | |
</div> | |
</div> | |
<!-- with error --> | |
<div class="clearfix error"> | |
<label for="bar">Bar</label> | |
<div class="input error"> | |
<input id="foo_bar" name="foo[bar]" size="30" value="" type="text"> | |
<span class="help-inline"></span> | |
</div> | |
</div> |
The solution I've arrived at is to first remove the "field_with_errors" div. This is done by setting the field_error_proc to simply return the html passed in without wrapping it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ./config/environment.rb | |
ActionView::Base.field_error_proc = Proc.new {|html, instance| html } |
The next step was to create a FormBuilder subclass with the desired functionality. The example below only demonstrates the 'text_field' method. In practice I'll have to create a separate method for each Bootstrap form element I want to use in my application.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ./app/helpers/boot_strap_form_builder.rb | |
class BootStrapFormBuilder < ActionView::Helpers::FormBuilder | |
def text_field(method, options={}) | |
t = @template | |
t.content_tag(:div, :class => "clearfix#{' error' unless @object.errors[method].blank?}") { | |
t.concat(t.label_tag method) | |
t.concat(t.content_tag(:div, :class => "input#{' error' unless @object.errors[method].blank?}") { | |
t.concat(super method) | |
if @object.errors[method].present? | |
t.concat(t.content_tag(:span, options[:help_text], :class => 'help-inline')) | |
end | |
}) | |
} | |
end | |
end |
Then to use the custom form builder I'd do somthing like this....
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%= form_for(@foo, :builder => BootStrapFormBuilder) do |f| %> | |
<%= f.error_explanations %> | |
<%= f.text_field :bar %> | |
<%= f.submit %> | |
<% end %> |
I realize this wasn't exactly a detailed explanation of a solution but hopefully I managed to get the gist of the idea across.
No comments:
Post a Comment