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 an 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 ... // Employment ->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 a 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.
On code plus sous forme de tableau depuis 1975…
De même le css ne doit pas se trouver dans un fichier html mais dans un fichier css pour une meilleure séparation des résponsabilité. Je t’invite à te renseigner sur le principe SOLID.
The web didn’t exist publicly before the late 1990s… Yes, separate CSS file is always good. This is an example in one file how to do it. There’s no one way to do things!