Introduction
In a form I’ve recently worked on using Symfony, I had to show a group of selectable checkboxes. In this case, the user can select any number of checkboxes also in one group, two of the checkboxes I needed to use JavaScript to detect when the box was selected. I wrote about that in my JavaScript Code Refactoring article.
There are two types of problems when using a ChoiceType built-in Field Type set to element type of checkboxes in Symfony:
- Rending in Twig is not easy
- Setting attributes is not easy, and may not work as you expect
The above two reasons are why I decided to write this article.
Example Code
Below is an example checkbox group that I created in a form class for some employment questions that are asked in a form:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
...
->add('employ', ChoiceType::class, array(
'mapped' => false,
'required' => false,
'expanded' => true,
'multiple' => true,
'label' => 'Employment',
'choices' => array(
'I have a job. # of hours/week:' => 'have_job',
'I am work study eligible' => 'work_study',
'I need assistance in finding a job' => 'find_work',
'I need to learn interviewing skills' => 'interview',
'I have no employment needs at this time' => 'no_needs',
'I volunteer for a non-profit organization' => 'non_profit',
'I need assistance with my resume' => 'resume',
'I need assistance finding an internship' => 'intern',
'I am undecided about my career or major' => 'major',
'Other:' => 'other',
),
))
...
}
Then when I tried to render in a single HTML table row in Twig, using code like this:
<tr><td>{{ form_widget(form.employ) }}</td></tr>
Then this appears like this rendering in a web page:

Notice the problem in that each checkbox
appears inline directly after each other. I tried to use the Twig nl2br filter together with “\n
” in my choice values, but that didn’t work since I really need another table row to show each of the checkboxes and labels.
Adding Checkboxes to TR
Since a ChoiceType in a Symfony form is an array of checkboxes, then we can use a Twig for loop to properly show the widget and label in a HTML table row. The Twig code needed is as follows:
{% for i in 1..8 %}
<tr><td> {{ form_widget(form.employ[i]) }}{{ form_label(form.employ[i]) }}</td></tr>
{% endfor %}
The unfortunate part of the above code is, in order to add an attribute like a JavaScript onchange, this has do be done in Twig on the particular element like so:
<tr><td> {{ form_widget(form.employ[0],{'attr':{'onchange':'changeJobHours()'}}) }}
{{ form_label(form.employ[0]) }} 
{{ form_label(form.job_hours) }}{{ form_widget(form.job_hours) }}</td></tr>
The above adds an onchange
attribute for the first checkbox. I also have a job hours and label, but those are hidden and shown when an onchange
event is triggered and box is selected.
Resultant Code
The overall resultant code looks like the following:
<table id='6th' style='border: 1px solid; margin-left: auto; margin-right: auto;
width: 50%; display: none;'
background="{{ asset('images/indneeds_assess/employment2.png') }}">
<tr><td colspan="2"><b>{{ form_label(form.employ) }}</b></td></tr>
<tr><td>{{ form_widget(form.employ) }}</td></tr>
<tr><td> {{ form_widget(form.employ[0],{'attr':{'onchange':'changeJobHours()'}}) }}
{{ form_label(form.employ[0]) }} 
{{ form_label(form.job_hours) }}{{ form_widget(form.job_hours) }}</td></tr>
{% for i in 1..8 %}
<tr><td> {{ form_widget(form.employ[i]) }}{{ form_label(form.employ[i]) }}</td></tr>
{% endfor %}
<tr><td> {{ form_widget(form.employ[9],{'attr':{'onchange':'changeEmploy()'}}) }}
{{ form_label(form.employ[9]) }} 
{{ form_label(form.employ_other) }}{{ form_widget(form.employ_other) }}</td></tr>
</table>
The above code puts each checkbox in on HTML tr
elements. The resultant web page looks like the following and appears much better than the original.

