Format form fields for bootstrap using rails+nokogiri
        Posted  
        
            by 
                user1116573
            
        on Stack Overflow
        
        See other posts from Stack Overflow
        
            or by user1116573
        
        
        
        Published on 2012-05-31T21:06:26Z
        Indexed on 
            2012/06/03
            10:40 UTC
        
        
        Read the original article
        Hit count: 295
        
I have the following in an initializer in a rails app that uses Twitter bootstrap so that it removes the div.field_with_errors that rails applies when validation fails on a field but also the initializer adds the help/validation text after the erroneous input field:
require 'nokogiri'
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  html = %(<div class="field_with_errors">#{html_tag}</div>).html_safe
  form_fields = [
    'textarea',
    'input',
    'select'
  ]
  elements = Nokogiri::HTML::DocumentFragment.parse(html_tag).css("label, " + form_fields.join(', '))
  elements.each do |e|
    if e.node_name.eql? 'label'
      html = %(#{e}).html_safe
    elsif form_fields.include? e.node_name
      if instance.error_message.kind_of?(Array)
        html = %(#{e}<span class="help-inline"> #{instance.error_message.join(',')}</span>).html_safe
      else
        html = %(#{e}<span class="help-inline"> #{instance.error_message}</span>).html_safe
      end
    end
  end
  html
end
This works fine but I also need to apply the .error class to the surrounding div.control-group for each error.
My initializer currently gives the following output:
<div class="control-group">
    <label class="control-label" for="post_message">Message</label>
    <div class="controls">
        <input id="post_message" name="post[message]" required="required" size="30" type="text" value="" /><span class="help-inline"> can't be blank</span>
    </div>
</div>
but I need something adding to my initializer so that it adds the .error class to the div.control-group like so:
<div class="control-group error">
    <label class="control-label" for="post_message">Message</label>
    <div class="controls">
        <input id="post_message" name="post[message]" required="required" size="30" type="text" value="" /><span class="help-inline"> can't be blank</span>
    </div>
</div>
The solution will probably need to allow for the fact that each validation error could have more than one label and input that are all within the same div.control-group (eg radio buttons / checkboxes / 2 text fields side by side).
I assume it needs some sort of e.at_xpath() to find the div.control-group parent and add the .error class to it but I'm not sure how to do this.
Can anyone help?
PS This may all be possible using the formtastic or simple_form gems but I'd rather just use my own html if possible.
EDIT
If I put e['class'] = 'foo' in the if e.node_name.eql? 'label' section then it applies the class to the label so I think I just need to find the parent tag of e and then apply an .error class to it but I can't figure out what the xpath would be to get from label to its div.control-group parent; no combination of dots, slashes or whatever seems to work but xpath isn't my strong point.
© Stack Overflow or respective owner