By default Symfony form fields temaplte renders goups of checkboxes or radio buttons listed linearly. It’s just a queue of label-input tags. It’s sometimes irritating when Front End Developer demands to wrap each label-input in the separated div tag. Of course Symfony developers thought it through and it’s easy to use our own form fields templates.
Let’s code
In your bundle create a file Resources/views/Form/fields.html.twig
If you don’t have a Form directory, create it.
{%- block choice_widget_expanded -%} <div class="expanded-group" {{ block('widget_container_attributes') }}> {%- for child in form %} <div class="expanded-row"> {{- form_widget(child) -}} {{- form_label(child, null, {translation_domain: choice_translation_domain}) -}} </div> {% endfor -%} </div> {%- endblock choice_widget_expanded -%}
And just tell Twig to use your new template. In file app/config/config.yml find twig section and add the Symfony path to your file.
# Twig Configuration twig: debug: "%kernel.debug%" strict_variables: "%kernel.debug%" form_themes: - "form/layout.html.twig" - "form/fields.html.twig" - 'PiciosLibBundle:Form:fields.html.twig'
The line
- 'PiciosLibBundle:Form:fields.html.twig'
should point to your bundle.
What we just did
We wrapped the loose label-input pairs in a div tag having a class expanded-row. It gives us more flexibility in styling those fields. Check also How to Customize Form Rendering.
Front End approach
We can achieve the same effect using Javascript. With JQuery it’s a piece of cake. Having such a HTML code:
<div id="user_permissions"> <input type="checkbox" id="user_permissions_1" name="user[permissions][]" value="1" checked="checked" /> <label for="user_permissions_1">User</label> <input type="checkbox" id="user_permissions_2" name="user[permissions][]" value="2" /> <label for="user_permissions_2">Admin</label> <input type="checkbox" id="user_permissions_3" name="user[permissions][]" value="3" checked="checked" /> <label for="user_permissions_3">Super Admin</label> </div>
We can use the simple function like this:
$(function() { wrap('user_permissions'); }); function wrap(id) { $('#'+id+' label').each(function() { var $parent = $(this).closest('#user_permissions'); var inputId = $(this).attr('for'); var $input = $('#' + inputId); var $row = new $('<div class="expanded-row"></div>'); $row.append($(this)).append($input); $parent.append($row); }); }