Bootstrap.js Styling a Collection in Symfony 2′s Form Builder

This was a task that took me a few hours to work out the solution, so I wanted to share it for other people to benefit from. I’m building a complicated form in Symfony 2.2.1 and I have many collections within it. I want to dynamically add rows to the collections. One is a collection of phone numbers, and I wanted to style it differently than every other row. I’m using Bootstrap.js to style the project, and wanted to apply some specific formatting to one row. See: Forms, Grid Sizing

Here’s how my page started out.

When you click on the “Add” buttons, you get the fields to add a new row. (The javascript and specific code you’ll need to make that work is in the Symfony Cookbook, under “How to Embed a Collection of Forms“)

Now, that’s ok, but here’s how I really wanted it to look:

Original Code

Here’s the original code to generate the Phone form. I’m going to try to limit this to showing only the code you need to make the specific change. You should be able to get everything else you need from the Symfony Cookbook if you don’t have it already.

First Changes

Okay, to get the dropdown and the input on the same row, we’ll first need to remove their labels, then set the class for each one. We can simply not render the label by using form_widget instead of form_row, and we can provide the class as an argument in form_widget. Don’t forget you need the ‘controls’ and ‘controls-row’ classes on the parent div.

It looks great now!

Or does it?

Final Solution

The problem is that when we use the add button, the generated code comes from that prototype definition. We’ll have to make some changes to the Type definition to fix this. Set the labels to false, and add the CSS class as well.


Note: At this point, you could revert the edit.html.twig template back to using form_row, but then you’ll run into a slight spacing issue with the bootstrap style and extra form_row divs, so I left it as is. If you’re using a different CSS framework to do this trick, you may want those divs.