Set the Input Labels for each Field as Headers in Symfony Collection Widget - forms

I have a form collection to add multiple "routes" on an editing page. For visual purposes I want this to be a horizontal list of inputs. So I've customized the collection_widget and it works great, it's integrated with jquery to add and delete records, etc. And very importantly I have headers above each column, with help text popups.
Problem
However, if the record does not have any routes yet, nothing shows up except the add button (i.e. the necessary headers are gone). And if I "add" a new route, it adds the prototype row, but it does NOT add the header titles. You'll see how I'm creating the <thead> below, and I simply do not understand enough about the variables available to know how to iterate through the available fields to get the names, even if there are no records yet.
Question
So how can I cycle through all the rows, and get the label for each input, so that I can create headers? Even if there is no data recorded yet.
Code
fields.html.twig
{% block collection_widget %}
{% spaceless %}
{% if prototype is defined %}
{% set attr = attr|merge({'data-prototype': block('collection_item_widget') }) %}
{% endif %}
{# We add the collection class to encapsulate the whole container #}
{% set attr = attr|merge({'class': (attr.class|default('') ~ ' collection')|trim}) %}
<div {{ block('widget_container_attributes') }}>
{{ form_errors(form) }}
<table class="table table-striped table-hover table-condensed">
<thead>
<tr>
{% set fieldNum = 1 %}
{% for rows in form %}
{# Only Loop through the headers once, regardless of how many rows there are. #}
{% if fieldNum == 1 %}
{% for row in rows %}
{# row.vars.label #}
<td class="heading{{ fieldNum }} heading_{{ row.vars.name }}">
<h4 class="collectionHeading">
{{ form_label(row) }}
</h4>
</td>
{% endfor %}
{% endif %}
{% set fieldNum = fieldNum + 1 %}
{% endfor %}
{# for delete row #}
<td class="heading{{ fieldNum }} heading_action"> </td>
</tr>
</thead>
<tbody>
{% for prototype in form %}
{{ block('collection_item_widget') }}
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="{{ fieldNum }}">
<div class="actionContainer">
<span class="action addCollection btn btn-primary btn-xs" title="Add"><span class="glyphicon glyphicon-plus"></span> Add</span>
</div>
</td>
</tr>
</tfoot>
</table>
{{ form_rest(form) }}
</div>
<div class="clear"></div>
{% endspaceless %}
{% endblock collection_widget %}
{% block collection_item_widget %}
{% spaceless %}
<tr class="collectionEntity">
{% set fieldNum = 1 %}
{% for row in prototype %}
<td class="field{{ fieldNum }} field_{{ row.vars.name }}">
{{ form_widget(row) }}
</td>
{% set fieldNum = fieldNum + 1 %}
{% endfor %}
<td class="field{{ fieldNum }} field_action">
<span class="action removeCollection btn btn-default glyphicon glyphicon-trash" title="Remove"></span>
</td>
</tr>
{% endspaceless %}
{% endblock collection_item_widget %}
Outputted HTML
<div id="contentSeoEditType_routing" data-prototype=" <tr class="collectionEntity"><td class="field1 field_furl"><div class="input-group"><span class="input-group-addon">/</span><input type="text"
id="contentSeoEditType_routing___name___furl" name="contentSeoEditType[routing][__name__][furl]" required="required" style="min-width: 200px" class="form-control inputType-text"
/></div></td><td class="field2 field_flagPrimary"><input type="radio"
id="contentSeoEditType_routing___name___flagPrimary" name="contentSeoEditType[routing][__name__][flagPrimary]" class="radioExclusive form-control inputType-checkbox" data-radioexclusive="routingFlagPrimary"
value="1" /></td><td class="field3 field_action"><span class="action removeCollection btn btn-default glyphicon glyphicon-trash" title="Remove"></span></td></tr>" class="collection">
<table class="table table-striped table-hover table-condensed">
<thead>
<tr>
<td class="heading1 heading_furl">
<h4 class="collectionHeading">
<label for="contentSeoEditType_routing_0_furl" class="required">Friendy URL</label><span class="required" title="This field is Required">*</span><span rel="popover" data-target=".popoverContent.help-contentSeoEditType_routing_0_furl" data-placement="right" class="popoverButton help-contentSeoEditType_routing_0_furl glyphicon glyphicon-question-sign" data-original-title="" title=""></span>
<div class="popoverContent help-contentSeoEditType_routing_0_furl"><em>Versioning:</em> Friendly URLs are <strong>not</strong> managed by the versioning system. Changes to the route will effect both the live and staging website. However, you can create extra aliases for testing and then change which is the primary route when you are ready to make them live.</div>
</h4>
</td>
<td class="heading1 heading_flagPrimary">
<h4 class="collectionHeading">
<span rel="popover" data-target=".popoverContent.help-contentSeoEditType_routing_0_flagPrimary" data-placement="right" class="popoverButton help-contentSeoEditType_routing_0_flagPrimary glyphicon glyphicon-question-sign" data-original-title="" title=""></span>
<div class="popoverContent help-contentSeoEditType_routing_0_flagPrimary"><em>Primary Route:</em> A page will have one primary Friendly URL. Additional aliases will redirect back to the primary URL.</div>
</h4>
</td>
<td class="heading3 heading_action"> </td>
</tr>
</thead>
<tbody>
<tr class="collectionEntity">
<td class="field1 field_furl">
<div class="input-group"><span class="input-group-addon">/</span><input type="text" id="contentSeoEditType_routing_0_furl" name="contentSeoEditType[routing][0][furl]" required="required" style="min-width: 200px" class="form-control inputType-text" value="Turkish-We-Love-You"></div>
</td>
<td class="field2 field_flagPrimary"><input type="radio" id="contentSeoEditType_routing_0_flagPrimary" name="contentSeoEditType[routing][0][flagPrimary]" class="radioExclusive form-control inputType-checkbox" data-radioexclusive="routingFlagPrimary" value="1" checked="checked"></td>
<td class="field3 field_action"><span class="action removeCollection btn btn-default glyphicon glyphicon-trash" title="Remove"></span></td>
</tr>
<tr class="collectionEntity">
<td class="field1 field_furl">
<div class="input-group"><span class="input-group-addon">/</span><input type="text" id="contentSeoEditType_routing_1_furl" name="contentSeoEditType[routing][1][furl]" required="required" style="min-width: 200px" class="form-control inputType-text" value="A-Dog-Named-Turkish"></div>
</td>
<td class="field2 field_flagPrimary"><input type="radio" id="contentSeoEditType_routing_1_flagPrimary" name="contentSeoEditType[routing][1][flagPrimary]" class="radioExclusive form-control inputType-checkbox" data-radioexclusive="routingFlagPrimary" value="1"></td>
<td class="field3 field_action"><span class="action removeCollection btn btn-default glyphicon glyphicon-trash" title="Remove"></span></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">
<div class="actionContainer"><span class="action addCollection btn btn-primary btn-xs" title="Add"><span class="glyphicon glyphicon-plus"></span> Add</span></div>
</td>
</tr>
</tfoot>
</table>
</div>
Ongoing Dilemma
This gets back to an overall frustration about the ongoing inability to do anything beyond the basics in the form template customizations. I can see what fields are available in any given context through documentation and iterating through the _context:
<ol>
{% for key, value in _context %}
<li>{{ key }} :
{% if value is not iterable%}
{{ value }}
{% else %}
{# WARNING! This causes the page to go blank white with no error. #}
{{ dump(value) }}
{% endif %}
</li>
{% endfor %}
</ol>
But this is a manual hack and does very little good because if the element is an object (which is when you really want to know), you can't dump it's value (it breaks the page, blank white with no error, which is another rabbit hole I got lost in for a day). And if I create nested for loops, they still don't print out much useful value information.
And just because the variable exists, it is sometimes empty in some block contexts and not others. And I have no idea how these blocks relate to one another or how the variables pass around between themselves, e.g.
{% block form_label %}
{{ parent() }}
{% if required is not empty %}
<span class="required" title="This field is Required">*</span>
{% endif %}
{{ block('form_help') }}
{% endblock %}
{# Custom Block for Help #}
{% block form_help %}
{% if help is not null %}
<span rel="popover" data-target=".popoverContent.help-{{ id }}" data-placement="right" class="popoverButton help-{{ id }} glyphicon glyphicon-question-sign"></span>
<div class="popoverContent help-{{ id }}">{{ help | raw }}</div>
{% endif %}
{% endblock %}
In some contexts I can call {{ block('form_help) }} and it works, but in others (e.g. from the {% block collection_widget %} it doesn't. I can print out _context in the {% block form_help %} and it will show a help variable, but it's empty. Why?
Variables Reference
There is documentation that explains how to access any public variable for a field called myFieldName by referencing the vars field, i.e. form.myFieldName.vars.publicVariable
<label for="{{ form.name.vars.id }}"
class="{{ form.name.vars.required ? 'required' : '' }}">
{{ form.name.vars.label }}
</label>
Additional variables are available for different field types, e.g. the collection Type has a prototype variable which contains a template of what the collection will look like.
{# this probably only works in your own template #}
{{ form_row(form.emails.vars.prototype) }}
{# this appears to work in the fields.html.twig master block template #}
{{ form_row(prototype) }}
But that doesn't help me figure out how to access the field labels to add a header. I also don't understand how these blocks pass variables back and forth to each other, e.g.
Reference
Documentation on Form Variables
Full List of Form Variables
Environment Details:
Using Symfony 2.5

Related

Create form in popup in Shopify (callback function)

I added form to button (in left top in header) https://en.partizanstore.eu/
I checked form in page and it works, but when I added form to snippet and to button, it dont work, dont send letter.
Can anybody help?
And by the way, can I create form anywhere, except on pages?
{% capture contact_form %}
<div class="contact">
{% form 'contact', class: 'contact__form' %}
{% if form.posted_successfully? %}
<div class="alert alert--success">
<span class="alert-title">{{ 'contact.form.successfully_sent' | t }}</span>
</div>
{% endif %}
{% if form.errors %}
<div class="alert alert--error">
<span class="alert__title">{{ 'general.forms.errors' | t }}</span>
{% include 'form_errors' %}
</div>
{% endif %}
<div class="form__control">
<label class="form__label" for="contact__name">{{ [ 'contact.form.name' | t }}</label>
<input type="text" id="contact__name" name="contact[name]">
</div>
<div class="form__control">
<label class="form__label" for="contact__phone">{{ 'contact.form.phone' | t }}</label>
<input type="text" id="contact__phone" name="contact[phone]">
</div>
<input type="submit" class="button button--primary" value="{{ 'contact.form.submit' | t }}">
{% endform %}
</div>
{% endcapture %}

SYMFONY FORM NULL on SUBMIT when embedded with conditional in a loop (and table) inside TWIG template

I had trouble with a SYMFONY FORM, it was providing NULL on SUBMIT.
After some research, I've found a workaround: I could get accurate value submitted with my form if I'd move the TWIG html code to render the form outside a table (Because the form I want to render should appear on an extended row of a table).
Here is what I had (case 1):
{% if list is defined %}
{% set table_root_id = pageName ~ '_table' %}
<div class='col-12'>
<table data-role='table' id='{{table_root_id}}_id' data-mode='reflow' class='table-reflow-breakpoint table-stripe col-12'>
<thead class='col-12'>
<tr class='col-12'>
<th class='col-2'>{{'MyBundle.id'|trans}}</th>
<th class='col-4'>{{'MyBundle.lastname'|trans}}</th>
<th class='col-4'>{{'MyBundle.firstname'|trans}}</th>
<th class='col-2'>{{'MyBundle.action'|trans}}</th>
</tr>
</thead>
<tbody class='col-12'>
{% for entity in list %}
{% set row_root_id = table_root_id ~ '_row_for_' ~ entity.id %}
<tr id = '{{row_root_id}}_id' class='col-12'>
<th class='col-2' >{{ entity.id }}</th>
<td class='col-4'>{{ entity.lastname }}</td>
<td class='col-4'>{{ entity.firstname }}</td>
<td class='col-2'>
<span class="ui-btn ui-btn-inline ui-btn-icon-notext ui-icon-user" title='{{"MyBundle.edit_user_profile"|trans}}' onclick='(new TableTupleButton("{{ table_root_id }}")).click({"route": "my_route", "page": "{{ pageName }}","post":{"entity_id_to_extend":"{{ entity.id }}}})'>
</span>
</td>
{% if app.request.session.get('entity_id_to_extend') == entity.id %}
{% set idOfContainerToInsertBelowTuple = 'container_of_'~ app.request.session.get('entity_id_to_extend') %}
<div class='col-12' id='{{ idOfContainerToInsertBelowTuple }}'>
{{ form(form_row_expanded) }}
</div>
<script type="text/javascript">
$(document).ready(new TableTupleButton('{{ table_root_id }}').extendRow('{{ idOfContainerToInsertBelowTuple }}','{{row_root_id}}'));
</script>
{% endif %}
</tr>
{% endfor %}
{% endif %}
What I had above did not work, and also {{ form(form_row_expanded) }} was rendered correctly, on a submit of that form, the value inside it were lost.
After few hours trying to spot the issue I found the following workaround (case 2):
{% set idOfContainerToInsertBelowTuple = 'container_of_'~ app.request.session.get('entity_id_to_extend') %}
<div class='col-12' id='{{ idOfContainerToInsertBelowTuple }}'>
{{ form(form_row_expanded) }}
</div>
{% if list is defined %}
{% set table_root_id = pageName ~ '_table' %}
<div class='col-12'>
<table data-role='table' id='{{table_root_id}}_id' data-mode='reflow' class='table-reflow-breakpoint table-stripe col-12'>
<thead class='col-12'>
<tr class='col-12'>
<th class='col-2'>{{'MyBundle.id'|trans}}</th>
<th class='col-4'>{{'MyBundle.lastname'|trans}}</th>
<th class='col-4'>{{'MyBundle.firstname'|trans}}</th>
<th class='col-2'>{{'MyBundle.action'|trans}}</th>
</tr>
</thead>
<tbody class='col-12'>
{% for entity in list %}
{% set row_root_id = table_root_id ~ '_row_for_' ~ entity.id %}
<tr id = '{{row_root_id}}_id' class='col-12'>
<th class='col-2' >{{ entity.id }}</th>
<td class='col-4'>{{ entity.lastname }}</td>
<td class='col-4'>{{ entity.firstname }}</td>
<td class='col-2'>
<span class="ui-btn ui-btn-inline ui-btn-icon-notext ui-icon-user" title='{{"MyBundle.edit_user_profile"|trans}}' onclick='(new TableTupleButton("{{ table_root_id }}")).click({"route": "my_route", "page": "{{ pageName }}","post":{"entity_id_to_extend":"{{ entity.id }}}})'>
</span>
</td>
{% if app.request.session.get('entity_id_to_extend') == entity.id %}
<script type="text/javascript">
$(document).ready(new TableTupleButton('{{ table_root_id }}').extendRow('{{ idOfContainerToInsertBelowTuple }}','{{row_root_id}}'));
</script>
{% endif %}
</tr>
{% endfor %}
{% endif %}
One notice I had to take {{ form(form_row_expanded) }} outside the loop thru "entity" so as to have the SUBMIT working properly and submitting the values.
I don't understand why it did not work in case 1? Could anyone give me some insight?
NB:
new TableTupleButton("{{ table_root_id }}")).click(...) is a JS
function to expand the row with the form (refresh the page telling
which row should be expanded);
new TableTupleButton('{{ table_root_id }}').extendRow(...)) is a JS
function to place an expanded row under the correct row under which
it should fit;

Jquery uploader not working In Twig File

Hi i am working on Symfony 2.4.2.I searched a multifile uploader for my application.
but in my Twig file where i am using this code its not working showing Error.
because of {% %} in twig we are using same syntax. can any one help me to figure out this.
If i am using this in HTML so its working.But i want it into TWIG file in Symfony.
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0,file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
<p class="name">{%=file.name%}</p>
{% if (file.error) { %}
<div>
<span class="label label-danger">Error</span> {%=file.error%} </div>
{% } %}
</td>
<td>
<p class="size">{%=o.formatFileSize(file.size)%}</p>
{% if (!o.files.error) { %}
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;"> </div>
</div>
{% } %}
</td>
<td>
{% if (!o.files.error && !i && !o.options.autoUpload) { %}
<button class="btn blue start btn-sm">
<i class="fa fa-upload"></i>
<span>Start</span>
</button>
{% } %}
{% if (!i) { %}
<button class="btn red cancel btn-sm">
<i class="fa fa-ban"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
Thanks in advance
Try putting your code between the autoescape tag in twig.
{% autoescape false %}
Everything will be outputted as is in this block
{% endautoescape %}
See this for reference and for more options:
http://twig.sensiolabs.org/doc/tags/autoescape.html
Edit:
If autoescaping (false) not working for you, then you may use the source function. Just output your file to a separate .html file and embed it via the source tag:
http://twig.sensiolabs.org/doc/functions/source.html
Thanks for this post:
How do I include raw HTML files in Symfony2/Twig templates?
Maybe you can try the "raw" tag. Not sure.
{% raw %}
your code here
{% endraw %}

Bootstrap 3: formatted checkboxes with Symfony & Twig

How to create a formatted group of checkboxes as described in the Bootstrap documentation using the Symfony Form Factory and Twig?
Using something like
<div class="row">
<div class="col-lg-4">
{{ form_label(form.sample) }}
</div>
<div class="col-lg-8">
{{ form_widget(form.sample) }}
</div>
</div>
will not result in the needed output:
a) each checkbox within a Bootstrap 3 structure like:
<div class="radio">
<label>
<input type="radio" ... />Option one
</label>
</div>
b) in addition the ability to output the checkboxes in two or more columns if needed:
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="radio"> ... </div>
</div>
<div class="col-lg-6 col-md-6">
<div class="radio"> ... </div>
</div>
</div>
The proper way to do this is to create your own form theme. I will not write the whole thing here, but what matters to you are those:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }} class="my-form-choices">
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block checkbox_widget %}
{% spaceless %}
<div class="checkbox">
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
</div>
{% endspaceless %}
{% endblock checkbox_widget %}
I removed the label rendering from the choice_widget_expanded so I could have the checkbox inside the label tag, just like what you have in your solution. But you can basically do whatever you want in your form theme. You can also overwrite radio_widget if you want to.
If you look closely at the div around the checkboxes, I gave it the class "my-form-choices". You could give it the classes you want. It could be "col-lg-8", like you have, but for me, it makes more sense to have a generic class name, and then use mixins in your own less file. Your less file would look like this:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
.my-form-row {
.make-row();
}
.my-form-choices {
.make-lg-column(8);
}
.my-form-row-label {
.make-lg-column(4);
}
But that's up to you. You don't have to do this if you don't want to. Finally, you use your theme by starting the twig for your page like this:
{% extends 'MyOwnBundle::layout.html.twig' %}
{% form_theme form 'MyOwnBundle:Component:formtype.html.twig' %}
And you display the row simply like that (the field I used in my test is availability, yours is sample):
{{ form_row(form.availability) }}
I've tried that (with Symfony 2.4), and it works. The output is something like that:
<div class="my-form-row">
<div class="my-form-row-label">
<label class="required">Availability</label>
</div>
<div class="my-form-choices" id="myown_website_contactmessage_availability">
<div class="checkbox">
<label for="myown_website_contactmessage_availability_0">
<input type="checkbox" value="morning" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_0">
Morning
</label>
</div>
<div class="checkbox">
<label for="myown_website_contactmessage_availability_1">
<input type="checkbox" value="afternoon" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_1">
Afternoon
</label>
</div>
<div class="checkbox">
<label for="myown_website_contactmessage_availability_2">
<input type="checkbox" value="evening" name="myown_website_contactmessage[availability][]" id="myown_website_contactmessage_availability_2">
Evening
</label>
</div>
</div>
</div>
Also notice that I do not have sub-rows, like you have in your solution. In fact, your solution goes beyond the question you were asking in the first place.
EDIT: here's a solution for having multiple columns
To have multiple columns, here is a quick solution. First, the form theme could be something like this:
{% block choice_widget_expanded %}
{% spaceless %}
<div class="my-form-choices-container">
<div {{ block('widget_container_attributes') }} class="my-form-choices">
{% for child in form %}
{{ form_widget(child) }}
{% endfor %}
</div>
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
{% block checkbox_widget %}
{% spaceless %}
<div class="my-form-choice">
<div class="checkbox">
<label for="{{ id }}"><input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans({}, translation_domain) }}</label>
</div>
</div>
{% endspaceless %}
{% endblock checkbox_widget %}
And then your less file would look like this:
#import '../../../../../../vendor/twitter/bootstrap/less/bootstrap.less';
.my-form-row {
.make-row();
}
.my-form-row-label {
.make-lg-column(4);
}
.my-form-choices-container {
.make-lg-column(8);
}
.my-form-choices {
.make-row();
}
.my-form-choice {
.make-md-column(6);
}
In this solution, you change the number of columns by changing the size of the columns. The cells should stack neatly. In this case, it is better to compile less (I won't explain that here). I have tried this solution, and it works well. The advantage of using less in this case, is that you can use the same form theme on multiple pages, and change the number of columns just by having a different "less" file for each of your pages.
You need to access to the form vars which contain the information about the checkboxes:
form.sample.vars.form.children
now you can loop through the checkboxes and access the values:
{% for children in form.sample.vars.form.children %}
<div class="checkbox>
<label>
<input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
{% if children.vars.label is defined %}
{{ children.vars.label|trans }}
{% else %}
{{ children.vars.value|capitalize|trans }}
{% endif %}
</label>
</div>
{% endfor %}
I place this code in a Twig template and add some logic to create rows with variable columns, so it look like this:
{% set cols = columns|default(1) %}
{% set i = 1 %}
{% for children in childrens %}
{% if i == 1 %}<div class="row">{% endif %}
<div class="col-lg-{{ 12/cols }} col-md-{{ 12/cols }}">
<div class="checkbox {{ class|default('') }}">
<label>
<input type="checkbox" name="{{ children.vars.full_name }}" id="{{ children.vars.id }}" value="{{ children.vars.value }}"{% if children.vars.data %} checked="checked"{% endif %} />
{% if children.vars.label is defined %}
{{ children.vars.label|trans }}
{% else %}
{{ children.vars.value|capitalize|trans }}
{% endif %}
</label>
</div>
</div>
{% set i = i+1 %}
{% if i > cols %}
</div>
{% set i = 1 %}
{% endif %}
{% endfor %}
{% if i != 1 %}</div>{% endif %}
now you can include this checkbox template where you need it:
<div class="row">
<div class="col-lg-4">
{{ form_label(form.sample) }}
</div>
<div class="col-lg-8">
{% include 'checkbox.twig' with {childrens:form.sample.vars.form.children, columns:2} only %}
</div>
</div>
the example above will return well formatted Bootstrap 3 output with checkboxes in two columns like this:
<div class="row">
<div class="col-lg-4">
<label class="required">Veranstalter</label>
</div>
<div class="col-lg-8">
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_0" value="DUMMY">Dummy</label>
</div>
</div>
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_1" value="DUMMY_1">Dummy 1</label>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6">
<div class="checkbox ">
<label><input type="checkbox" name="form[sample][]" id="form_sample_2" value="DUMMY_2">Dummy 2</label>
</div>
</div>
</div>
It's easy to use and will also work for radio buttons - just replace the class "checkbox" with "radio".
Ran into this issue today and thought I'd share my solution. I already had a form input override file, but didn't like what I found elsewhere. So wrote a form_label block override like so.
{% block form_label -%}
{% if label is not sameas(false) -%}
{% 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 %}
{% if label is empty -%}
{% set label = name|humanize %}
{%- endif -%}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{% if 'checkbox' in block_prefixes %}{{ form_widget(form) }}{% endif %}{{ label|trans({}, translation_domain) }}</label>
{%- endif %}
{%- endblock form_label %}
Then the form_row block like so:
{% block form_row %}
{% spaceless %}
{% if 'checkbox' not in block_prefixes %}
<div class="form-group">
{{ form_label(form) }}
{{ form_errors(form) }}
{% if 'datetime' not in block_prefixes %}
{{ form_widget(form, { 'attr': {'class': 'form-control'} }) }}
{% else %}
{{ form_widget(form) }}
{% endif %}
</div>
{% else %}
{% import _self as forms %}
<div class="checkbox">
{{ form_label(form) }}
</div>
{% endif %}
{% endspaceless %}
{% endblock %}
I choose this method because it allowed me to continue to use the basic form(form) method in templates. Hope this helps you.
If you're looking for the simple version of this answer (ie you've already applied the bootstrap_3_layout theme to your form and just want to apply custom label text)
{{ form_widget( form.field, { 'label': 'Custom Label Text' } ) }}

Symfony2: preventing radio widgets from rendering labels

I'm attempting to customise the form layouts using Twig in symfony2. I am aiming to render a radio input that looks something like this...
<label class=" required">Label name</label>
<span class="form-radio">
<input type="radio" name="album_has_subalbums_1" /> Yes
</span>
<span class="form-radio">
<input type="radio" name="album_has_subalbums_0" /> No
</span>
I have overridden the radio_widget block in my custom form theme as follows
{% block radio_widget %}
{% spaceless %}
<span class='form-radio'>
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
</span>
{% endspaceless %}
{% endblock radio_widget %}
However, this renders the following markup:
<label class=" required">Label name</label>
<span class="form-radio">
<input type="radio" id="album_has_subalbums_1" name="album[has_subalbums]" required="required" value="1">
</span>
<label for="album_has_subalbums_1" class=" required">Yes</label>
<span class="form-radio">
<input type="radio" id="album_has_subalbums_0" name="album[has_subalbums]" required="required" value="0">
</span>
<label for="album_has_subalbums_0" class=" required">No</label>
Basically, for each radio input element its creating a label to identify whether the value for it is Yes or No. I'm working with a pre-existing design so I can't easily tweak the html markup.
How can I prevent the radio inputs from generating the selection texts as labels? I know it calls the field_label block internally, but as you can see my radio_widget doesn't make reference to it, so I'm a little lost as to how to prevent this behaviour.
EDIT:
To be clear, I want the same kind of structure as my first example... I have left out the name and value attributes etc, but obviously its just for demonstration purposes.
What you need to override is not the radio_widget block, but the choice_widget one:
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ child.get('label') | trans }} {# <- this is what you need #}
{# leave the rest untouched #}
And don't forget to clear the cache for this change to take effect.