Reputation: 613
Question about symfony2 form component and its templating:
I've got a bunch of checkboxes to style (about 10 in one form row). Usually I use <label>
tag this way: <label><input/> some text</label>
but I can't find a way to change it in the form template (form_div_layout.html.twig). I can't even find a way to wrap any tag around input widget and its label and I always end up with markup like this: <input/> <some_tag><label>some text</label></some_tag>
or <some_tag><input/></some_tag> <label>some text</label>
which is not very useful, to say the least...
Googled quite a bit, but couldn't find an answer.
Upvotes: 7
Views: 8035
Reputation: 6913
I think this is what you are looking for: http://symfony.com/doc/current/book/templating.html#overriding-bundle-templates
You can override any of the default twig templates by creating another file with the same name in your app/resources folder.
In your case you want to override the form_div_layout.html.twig template, copy it from the bundle to app/Resources/TwigBundle/views/Form/form_div_layout.html.twig, customize away and symfony will use that rather than the default.
EDIT: Once you have overridden the template you could modify the {% block checkbox_widget %}
to have the input wrapped with the label tags using the twig vars
<label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>
{{label|trans }}
<input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
</label>
You will also need to remove the 'generic_label' definition, meaning every other block requires modifications.
Upvotes: 4
Reputation: 2254
It is possible to define blocks for the rows of specific form widget types, e.g. {% block checkbox_row %}
. I discovered this here: http://forum.symfony-project.org/viewtopic.php?f=23&t=57986#p153546
All that is then required to wrap the label around the widget for checkboxes is the following:
{% block checkbox_row %}
{% spaceless %}
<div>
{% if not compound %}
{% set label_attr = label_attr|merge({'for': id}) %}
{% endif %}
{% if required %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}
{{ form_widget(form) }}
{% if label is empty %}
{% set label = name|humanize %}
{% endif %}
</label>
{{ form_errors(form) }}
</div>
{% endspaceless %}
{% endblock checkbox_row %}
The label code has been copied and pasted from {% block form_label %}
. I've put the form error below the widget as I'm using Zurb's Foundation framework.
The code for radio buttons, is more complicated because {% block radio_row %}
doesn't appear to exist, so you have to take Whistlegreg's advice and edit the {% block choice_widget %}
block, in Symfony 2.1 that's actually now the {% block choice_widget_expanded %}
. Here's my code:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{% set child_label = child.get('label') %}
{% if child_label is not sameas(false) %}
{% set child_id = child.get('id') %}
{% set child_compound = child.get('compound') %}
{% set child_required = child.get('required') %}
{% set child_label_attr = child.get('label_attr') %}
{% if not child_compound %}
{% set child_label_attr = child_label_attr|merge({'for': child_id}) %}
{% endif %}
{% if child_required %}
{% set child_label_attr = child_label_attr|merge({'class': (child_label_attr.class|default('') ~ ' required')|trim}) %}
{% endif %}
<label{% for attrname, attrvalue in child_label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{% endif %}
{{ form_widget(child) }}
{% if child_label is not sameas(false) %}
{% if child_label is empty %}
{% set child_label = name|humanize %}
{% endif %}
{{ child_label|trans({}, translation_domain) }}
</label>
{% endif %}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
Tested and working in Symfony 2.1.9 DEV.
Upvotes: 1
Reputation: 3872
Whistlegreg is correct that you will need to override the twig form templates. However, you do not need to remove the {% block generic_label %}
block. See his answer if you need help on how to override the templates.
In order to wrap the checkbox input tags with a label, the first step will be to override the {% block choice_widget %}
block and remove the {{ form_label(child) }}
line from the {% if expanded %}
section that prints out a separate label.
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{# {{ form_label(child) }} <--------------------- remove this line #}
{% endfor %}
</div>
{% else %}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if empty_value is not none %}
<option value="">{{ empty_value|trans }}</option>
{% endif %}
{% if preferred_choices|length > 0 %}
{% set options = preferred_choices %}
{{ block('widget_choice_options') }}
{% if choices|length > 0 and separator is not none %}
<option disabled="disabled">{{ separator }}</option>
{% endif %}
{% endif %}
{% set options = choices %}
{{ block('widget_choice_options') }}
</select>
{% endif %}
{% endspaceless %}
{% endblock choice_widget %}
Now you will just need to handle printing the label in the {% block checkbox_widget %}
block.
{% block checkbox_widget %}
{% spaceless %}
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans }}</label>
{% endspaceless %}
{% endblock checkbox_widget %}
You will need to do the same for {% block radio_widget %}
since it would not otherwise have a label now.
{% block radio_widget %}
{% spaceless %}
<label for="{{ id }}"><input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans }}</label>
{% endspaceless %}
{% endblock radio_widget %}
Upvotes: 6
Reputation: 1204
I think you can do it by changing the form_row block.
Try something like this:
{% block form_row %}
{% spaceless %}
<label>
{{ form_widget(form) }}
</label>
{% endspaceless %}
{% endblock form_row %}
But take care, it's definitively not a very flexible solution...
You should probably use this only with a specific Type, not for all.
Anyway, you must use form_row
to get it work.
Upvotes: 0