Formtastic is pretty killer when it comes to creating nice looking forms very quickly. I love the short syntax compared to the default Rails form helpers, but sometimes I find the black box helpers a bit restricting when it comes to customizing the forms. Usually modifying the CSS is enough to get desired results, but I ran into a case today where it would have been an ugly hack to make it work with CSS.
Problem
I need to add HTML inside the <li> tag that is produced by the formtastic input helper. The helper produces HTML that looks like this:
I want to insert a link in betweent the input field and the inline hints. This is not possible, since the formtastic input helper outputs this entire HTML snippet. You can customize plenty of things within the helper, but I did not see a way to add more html content.
Solution
As I started to dig through the formtastic source I noticed that all of the input elements are using a wrapper module that produces the content inside the <li> tag. Take a look at this module:
All of the Formtastic input classes (StringInput, TextInput, HiddenInput,etc..) pass a block to the input_wrapping method inside their to_html method. The content_tag method takes the element name, content and element options as arguments. See here for more info: http://apidock.com/rails/ActionView/Helpers/TagHelper/content_tag
In order to add my content, I will need to add a String element (my HTML) to this array:
As you can see in the code above, it is just an array of strings that are joined together by carriage returns and marked as safe using the Rails String core_ext html_safe. So I will have to insert my HTML code in the desired position of this array. In my scenario, it makes sense to put the extra HTML between the input tag and the error html. I decided to monkey patch this method (oops, maybe dangerous if I ever upgrade formtastic for this app). I added this code to /app/config/initializers/formtastic_monkey_patch.rb:
The first thing I needed to patch was the Html module. 3 methods were added to this module to allow me to pass :extra_html and :extra_html_class to the formtastic input helper. This was pretty much a copy/paste from “Formtastic::Inputs::Base::Hints”. Then I just had to add the “extra_html” to the array inside the “input_wrapping” method. Now I can do this in my form:
This will output:
I can take this a step further by adding another option for the order that the extra html will appear inside the <li> tag. New monkey patch:
I added one method inside the Html class to set a default extra_html_position within the options hash. Then I modified “input wrapping” so it inserts the extra_html into the specified position. Here is the new formtastic input call in my view:
By passing the :extra_html_position option with a value of zero, formtastic will now insert the extra_html before the input tag. So there ya go… monkey-patched and ready to roll.







