Zoltán Süle
Zoltán Süle

Reputation: 1702

wrap checkboxes with custom html in Twig template using form entity fieldtype (Symfony3)

I would like to wrap the checkboxes with custom HTML in twig template when Symfony3 renders the form.

Instead of this:

<input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
<label for="form_role_1">ROLE 1</label>
<input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
<label for="form_role_2">ROLE 2</label>
<input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
<label for="form_role_3">ROLE 3</label>

I would like to get something like this:

<div class="input-group">
    <input type="checkbox" id="form_role_1" name="form[role][]" value="1" />
    <label for="form_role_1">ROLE 1</label>
</div>

<div class="input-group">
    <input type="checkbox" id="form_role_2" name="form[role][]" value="2" />
    <label for="form_role_2">ROLE 2</label>
</div>

<div class="input-group">
    <input type="checkbox" id="form_role_3" name="form[role][]" value="3" />
    <label for="form_role_3">ROLE 3</label>
</div>

in the controller action:

    $form = $this->createForm(RolesFormType::class, $roles);
    $form->handleRequest($request);

    return $this->render(
        'role/edit_roles.html.twig',
        array(
            'form' => $form->createView()
        )
    );

in the form type:

class RolesFormType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('role', EntityType::class, array(
                'label' => 'form.elements.roles',
                'class' => 'RoleBundle\Entity\Role',
                'choice_label' => 'role_name',
                'expanded' => true,
                'multiple' => true
        ));
    }
}

the classic template looks like this:

    <div class="container-fluid">
        <div class="row">

            {{ form_start(form, {'method': "POST"}) }}

            <div class="col-md-12">

                <div class="form-group">
                    {{ form_errors(form.role) }}
                    {{ form_widget(form.role, {}) }}
                </div>

            </div>

            {{ form_rest(form) }}
            {{ form_end(form) }}

        </div>
    </div>

I tried it this way in the twig template, but only the labels were rendered:

    <div class="container-fluid">
        <div class="row">

            {{ form_start(form, {'method': "POST"}) }}

            <div class="col-md-12">

                {% for role in form.role %}
                <div class="input-group">
                    {{ form_label(role) }}
                    {{ form_widget(role) }}
                </div>
                {% endfor %}

            </div>

            {{ form_rest(form) }}
            {{ form_end(form) }}

        </div>
    </div>

Is ii possible without creating a new field type?

solution

concerning @xabbuh's answer I found the solution at How to Customize Form Rendering in Symfony 3

I created a folder in my Bundle: src/RoleBundle/Resources/views/form

and I put a new file (fields.html.twig) into it with this content

{%- block choice_widget_expanded -%}
    <div {{ block('widget_container_attributes') }}>
        {%- for child in form %}
        <div class="input-group">
            {{- form_widget(child) -}}
            {{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
        </div>
        {% endfor -%}
    </div>
{%- endblock choice_widget_expanded -%}

In the meantime I found another question which deals with this problem: Overriding symfony radio widget

Upvotes: 2

Views: 4094

Answers (2)

coffey
coffey

Reputation: 11

When I play with symfony is not very skilled, I don't often use this accepted solution to solve it

view:

<label class="layui-form-label">所属地市:</label>
                <div class="layui-inline">
                    <select name="{{ form.cityId.vars.full_name }}"  lay-verify="" id="{{ form.cityId.vars.id }}" lay-filter="case_city">
                        <option value="0">请选择</option>
                        {% if citylist is not empty %}
                            {% for list in citylist %}
                                <option value="{{ list.id is defined ? list.id : 0 }}">{{ list.areaName is defined ? list.areaName : '' }}</option>
                            {% endfor %}
                        {% endif %}
                    </select>
                </div>

controller:

$caseReg = new CaseRegister();
    $form = $this->createForm('Alarm\Component\Form\CaseRegisterType', $caseReg);
    $form->handleRequest($request);
    $citylist = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->findBy(array('pid'=>0,'status'=>0));
    $caseType = $this->getDoctrine()->getRepository('AlarmComponent:CaseType')->findBy(array('status'=>0));
    if ($form->isSubmitted()) {
        $em = $this->getDoctrine()->getManager();
        $param = $request->request->get('alarm_component_caseregister');
        if($param['receiveId'] == 0)
        {
            $case = new CaseType();
            $case->setCaseName($param['receiveName']);
            $em->persist($case);
            $em->flush($case);
            $caseReg->setReceiveId($case->getId());
            $caseReg->setReceiveName($case->getCaseName());
        }
        if($param['cityId'] != 0)
        {
            $city = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['cityId']);
            $caseReg->setCityId($city);
        }

        if($param['subofficeId'] != 0)
        {
            $suboffice = $this->getDoctrine()->getRepository('AlarmComponent:OfficeArea')->find($param['subofficeId']);
            $caseReg->setSubofficeId($suboffice);
        }
        $em->persist($caseReg);
        $em->flush($caseReg);
        return $this->redirectToRoute('case_register_index');
    }
    return $this->render('AlarmWebBundle:BackendBat\CaseRegister:new.html.twig', array(
        'caseReg'   =>  $caseReg,
        'form'      =>  $form->createView(),
        'citylist'  =>  $citylist,
        'casetype'  =>  $caseType
    ));

It is also can solve my problem, but when I was late to optimize this or they must be altered. But I hope this answer can solve your current problem.

Upvotes: 1

xabbuh
xabbuh

Reputation: 5881

You can customise the rendering of your form using a custom form theme. You can so either on the project level or even do that just for a particular form (see How to Customize Form Rendering and How to Work with Form Themes for more information).

Your example looks like you need to override the choice_widget and choice_label

Upvotes: 3

Related Questions