Display Checkbox Group Properly in Twig


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:

  1. Rending in Twig is not easy.
  2. 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:

TwigRender

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>&emsp;{{ 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>&emsp;{{ form_widget(form.employ[0],{'attr':{'onchange':'changeJobHours()'}}) }}
   {{ form_label(form.employ[0]) }}&emsp;
   {{ 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>&emsp;{{ form_widget(form.employ[0],{'attr':{'onchange':'changeJobHours()'}}) }}
      {{ form_label(form.employ[0]) }}&emsp;
      {{ form_label(form.job_hours) }}{{ form_widget(form.job_hours) }}</td></tr>
   {% for i in 1..8 %}
      <tr><td>&emsp;{{ form_widget(form.employ[i]) }}{{ form_label(form.employ[i]) }}</td></tr>
   {% endfor %}
   <tr><td>&emsp;{{ form_widget(form.employ[9],{'attr':{'onchange':'changeEmploy()'}}) }}
      {{ form_label(form.employ[9]) }}&emsp;
      {{ 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.

Employment

Advertisements

About Alvin Bunk
Hi, I'm a software developer at Taft College.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: