Overriding checkbox form field producing duplicate label and no field in Symfony 4.4

341 Views Asked by At

I am having trouble overriding a checkbox field in my Symfony form inside my Twig template.

I am building the field with the following code in my Twig template:

{{ form_row(form.legal, {
   'label' : 'personal.form.fields.legal'|trans,
}) }}

In the same template I have the following block where I am attempting to customise the label. Note the translation above includes HTML which is why I need the raw filter.

{% block _crmpiccobundle_details_legal_label %}
    {% apply spaceless %}
        <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
            {{ label|unescape|raw }}
        </label>
    {% endapply %}
{%- endblock %}

Unfortunately, this doesn't work and bizarrely leaves me with no checkbox and a duplicate label and I can't work out why.

2

There are 2 best solutions below

0
xtx On

Looks like you are using a bootstrap based form theme (like bootstrap_4_layout.html.twig or bootstrap_3_layout.html.twig)

Try doing like this:

{% block _crmpiccobundle_details_legal_label %}
    {%- if widget is defined -%}
        {{ widget|raw }}
        
        {% apply spaceless %}
            <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
                {{ label|unescape|raw }}
            </label>
        {% endapply %}
        
    {%- endif -%}
{%- endblock %}

In bootstrap layout, widget part needs to be wrapped into label, so the theme calls the same block twice, first for _label part and second time for _widget. For the second call, theme provides widget variable, which you have to render yourself (otherwise you wouldn't see your checkbox). Also, you have to suppress label being rendered twice, which could be done just by checking whether widget is defined.

See how the original block also checks whether widget is defined to avoid double label rendering:

https://github.com/symfony/symfony/blob/e2f430dfb4c0c8cdde01ed111f4f0851e268ab5a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig#L83

0
Jysuss On

I found a solution to the same problem in boostrap_5_layout.

If you don't call {% use "bootstrap_base_layout.html.twig" %} at the top it will give you a double label and a double div.form-check.

So just add like that and it's work for me.

{% use "bootstrap_5_layout.html.twig" %}
{% use "bootstrap_base_layout.html.twig" %}

{%- block checkbox_widget -%}
    {%- set attr_class = attr_class|default(attr.class|default('')) -%}
    {%- set row_class = '' -%}
    {%- if 'btn-check' not in attr_class -%}
        {%- set attr_class = attr_class ~ ' form-check-input' -%}
        {%- set row_class = 'form-check' -%}
    {%- endif -%}
    {%- set attr = attr|merge({class: attr_class|trim}) -%}
    {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
    {%- if 'checkbox-inline' in parent_label_class %}
        {%- set row_class = row_class ~ ' form-check-inline' -%}
    {% endif -%}
    {%- if 'checkbox-switch' in parent_label_class %}
        {%- set row_class = row_class ~ ' form-switch' -%}
    {% endif -%}
    {%- if row_class is not empty -%}
        <div class="{{ row_class }}">
    {%- endif -%}
    {{- form_label(form, null, { widget: parent() }) -}}
    {%- if row_class is not empty -%}
        </div>
    {%- endif -%}
{%- endblock checkbox_widget %}