Remove or customize the embeded form label - symfony

When I set up my formtype file like this:
$builder->add( 'producer', new ProducerType() );
it always return me a general title(label) for the embeded form, like "producer", how can I remove or customize this label?
UPDATE: the latest Fosuserbundle has been removed this annoyed lable

The correct(?) way of removing the label is to set it to false.
$builder->add( 'producer', new ProducerType(), array( 'label' => false ));
Then the tag won't be rendered at all. Altough it's somehow missing in the documentation at the moment, you can refactor this behaviour by looking at the default twig form styles (3rd line):
{% block form_label %}
{% spaceless %}
{% 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 %}>{{ label|trans({}, translation_domain) }}</label>
{% endif %}
{% endspaceless %}
{% endblock form_label %}
Those twig styles are also a great start for form customization. More on this topic can be found in this cookbook entry.

you can try adding a label as an option, depending on what options ProductType is inheriting this may be enough.
$builder->add('producer', new ProducerType(), array('label' => 'Some Label'));

To get an empty embedded form label try adding an empty (one space char) label attribute
$builder->add( 'producer', new ProducerType(), array('label' => ' '))
which results to something like the following:
<div id="producer">
<div>
<label class=" required"></label>
<div id="mainEntityName_producer">
<div>
<label.../>
<input.../>
</div>
</div>
</div>
</div>

To avoid fighting with formbuilder, you can disable labels using css.
<style>
table.record_properties td label {
display: none;
}
</style>
<form action="{{ path('equipment_update', { 'id': entity.id }) }}" method="post" {{ form_enctype(edit_form) }}>
<table class="record_properties" style="text-align: left;width: 500px;">
<tbody>
<tr>
<th>{% trans %}title{% endtrans %}</th>
<td> </td>
<td>{{ form_row(edit_form.title) }}</td>
</tr>
...

Related

Symfony2, a label Token appears when using form themes

I'm using Symfony2.6 , and I'm trying to customize form rendering. The problem that when I put {{ form_rest(form) }} into the form , a label Token appears. How can I make it hidden ?
This is the form theme
{% extends 'form_div_layout.html.twig' %}
{% block form_widget_simple %}
<div class="form-group">
{{ form_label(form, null, {'label_attr': {'class': 'control-label'}}) }}
{{ parent() }}
</div>
{% endblock %}
When I remove the block {% block form_widget_simple %} to test what gives , the Token label become hidden.
Edit:
I'd like to know also if it's correct to change the simple widget block and render inside it a label or no.
You've changed the block of the simple widget which shouldn't render a label (and it doesn't by default). If you really need to do it this way, you may check the type variable and do not render label for the hidden type. Something as following:
{% block form_widget_simple %}
<div class="form-group">
{% if type != 'hidden' %}
{{ form_label(form, null, {'label_attr': {'class': 'control-label'}}) }}
{% endif %}
{{ parent() }}
</div>
{% endblock %}
This works fine :
{% extends 'form_div_layout.html.twig' %}
//........
{%- block hidden_row -%}
<div style="display:none">
{{ form_widget(form) }}
</div>
{%- endblock hidden_row -%}

Customising form labels in Symfony

I have a symfony page where I display a form, and I would like to add an
* in the labels of all fields that are required.
So I have my form.php.twig, that looks like this:
{% extends "::layout.php.twig" %}
{% block body %}
<div class="row">
{% use 'form_div_layout.html.twig' with form_label as base_form_label %}
{% block form_label %}
{{ block('base_form_label') }}
{% if required %}
<span class="required" title="This field is required">*</span>
{% endif %}
{% endblock %}
</div>
{% endblock %}
I followed the exact documentation of the symfony cookbook on how to customise labels, which is http://symfony.com/doc/current/cookbook/form/form_customization.html#cookbook-form-theming-methods.
But I keep getting this error
Variable "label" does not exist in form_div_layout.html.twig at line 206
I don't have any label variable in the code of my form.php.twig so I don't see why I get this error. And when I remove the
{{ block('base_form_label') }}
I get
Variable "required" does not exist in ATPlatformBundle:Session:create.php.twig
Can anyone help me on this? I don't see where is my mistake? I am not looking to customise it with css, but to add the * .
I have checked the form_div_layout.html.twig at line 206 and this is what there is
{%- 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 -%}
{%- if label_format is not empty -%}
{% set label = label_format|replace({
'%name%': name,
'%id%': id,
}) %}
{%- else -%}
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ translation_domain is sameas(false) ? label : label|trans({}, translation_domain) }}</label>
{%- endif -%}
{%- endblock form_label -%}
Thank you in advance.
Did you try defining the label from inside your form builder?! The below field is a required one because unless you mention required => false, your field will be rendered as required.
Something like:
->add('name', 'text', array('label' => '* name'))
With Twig, you should have to test the existence of a variable before using it:
Variable "required" does not exist
{% if required is defined and ... }
You need to test this because you field isn't always required.
if you want further information, you have this page of the documentation:
http://twig.sensiolabs.org/doc/tests/defined.html
Ok, so at the end, I didn't manage to change labels within my form.php.twig (which is the template I use to display my form), but I used another technique.
I created a new file named fields.php.twig, which I put in MyBundle/Resources/views/Form.
At the beginning of my fields.php.twig, I then added
{% extends 'form_div_layout.html.twig' %}
and below it, I added
{% block form_label %}
{{ parent() }}
{% if required %}
<span> * </span>
{% endif %}
{% endblock form_label %}
Then in my form.php.twig, I added
{% form_theme form 'MyBundle:Form:fields.php.twig' %}
{{ form_start(form) }}
Myform here with {{ form_label(form.property) }}
{{ form_errors(form.property) }}
{{ form_widget(form.property) }}
{{ form_end(form) }}
It works perfectly, but I had to create the fields.php.twig.

Twig - Why can't I access a variable I've set?

For some reason, a variable I'm setting in one form template bloc is not available in a child form block.
I have an 'entity' field type to present a selection of checkboxes to allow the user to select related items...
$builder
->add( 'title' )
->add(
'apps',
'entity',
[
'class' => 'OurAdminBundle:App',
'choices' => $apps,
'property' => 'title',
'expanded' => true,
'multiple' => true
]
)
And here's the template that renders the form
// Effectively imported using the MopaBootstrapBundle
// {% form_theme form 'OurAdminBundle:Form:fields.html.twig %}
// Further in page theming
{% form_theme form _self %}
// Set variable when on the apps field, so it should be available to all child
// forms
{% block _gallery_apps_widget %}
{% set custom_checkboxes = 1 %}
{{ block('choice_widget') }}
{% endblock %}
// Attempt to retrieve the variable on the checkboxes within the apps entity
/ field
{% block checkbox_widget %}
{{ dump(custom_checkboxes|default(0) }} // Displays 0
{% endblock checkbox_widget %}
Here's the code from the fields.html.twig file (with minor debugging additions...
{% block choice_widget_expanded %}
{{ dump(custom_checkboxes|default(0)) }}
{% set custom_checkboxes = custom_checkboxes|default(0) %}
{{ dump(custom_checkboxes|default(0)) }}
{% spaceless %}
{% set label_attr = label_attr|merge({'class': (label_attr.class|default(''))}) %}
{% set label_attr = label_attr|merge({'class': (label_attr.class ~ ' ' ~ (widget_type != '' ? (multiple ? 'checkbox' : 'radio') ~ '-' ~ widget_type : ''))}) %}
{% if expanded %}
{% set attr = attr|merge({'class': attr.class|default(horizontal_input_wrapper_class)}) %}
{% endif %}
{% for child in form %}
{% if widget_type != 'inline' %}
<div class="{{ multiple ? 'checkbox' : 'radio' }}">
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ form_widget(child, {'horizontal_label_class': horizontal_label_class, 'horizontal_input_wrapper_class': horizontal_input_wrapper_class, 'attr': {'class': attr.widget_class|default('')}}) }}
{{ child.vars.label|trans({}, translation_domain) }}
</label>
{% if widget_type != 'inline' %}
</div>
{% endif %}
{% endfor %}
{% endspaceless %}
{% endblock choice_widget_expanded %}
... which successfully displays '1' on both counts.
I've racked my brains over this one, but can't for the life of me understand why I can't access the variable in the checkbox_widget block. Please help.
This is due to how Symfony renders form fields when calling form_widget() or any other form* family of functions.
Symfony creates a new separate scope which do not share the scope of the parent (in order to prevent scope polluting while rendering fields).
If you which to pass a variable to the checkbox widget, edit the form_widget call in the choice_widget_expanded to pass on the custom_checkboxes as so (added tabbing for clarity only):
{{ form_widget(child, {
'horizontal_label_class': horizontal_label_class,
'horizontal_input_wrapper_class': horizontal_input_wrapper_class,
'attr': {'class': attr.widget_class|default('')},
'custom_checkboxes': custom_checkboxes
}) }}

Update from 2.0 to 2.1: Class for <label> gets lost on it's way

I just updated symfony2 from 2.0.16 to 2.1.2 and now I've got the problem, that my class for the label isn't added anymore.
In the Twig-template I include the field like this:
<div class="row{% if form_errors(form.object) %} _error{% endif %}">
{{ form_label(form.object, null, { 'attr': {'class': '_hint'} }) }}
{{ form_widget(form.object, { 'attr': {'class': 'c6'} }) }}
</div>
And my extension of the default form layout looks like this:
{% use 'form_div_layout.html.twig' with field_label as base_field_label %}
{% block field_label %}
{{ block('base_field_label') }}
{% if attr.class is defined and '_hint' == attr.class %}
<div>
some
</div>
{% endif %}
{% endblock %}
The strange thing is, that the attr.class value is set, as the <div> gets rendered. But the class is not added to the <label> anymore.
you should overwrite a form_label block instead of field_label because field_label is deprecated
You should use a label_attr array instead of attr, ie:
{% if label_attr.class is defined and '_hint' == label_attr.class %}

How to add a css class on a "form_row" in twig template

I would like to know how I can add a css class on a "{{ form_row() }}" in twig. For the moment, I have this code :
{{ form_row(form.username, {'label' : "Login", 'attr': {'class': 'loginForm'}}) }}
... But the CSS class "loginForm" isn't used in the HTML code.
Thank you :) !
If you want the common class for the form_row (it means one class for form_label, form_widget and form_errors), you should customize a field_row block.
This article explains how to customize form fields: How to customize Form Rendering.
There are some methods to do this.
For example I'm using Method 2 (How to customize Form Rendering: Method 2):
{% extends 'form_div_layout.html.twig' %}
{% block field_row %}
{% spaceless %}
{% set class='' %}
{% if attr.class is defined %}
{% set class = 'class="' ~ attr.class ~ '"' %}
{% endif %}
<div {{ class }} >
{{ form_label(form, label|default(null)) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock field_row %}
My answer is very similar to nni6's but it allows you to pass through the entire attr array.
My HTML structure is for Twitter Bootstrap but you can have whatever you want. This example also places an error class on the wrapper div if there are any errors - this part is not required but is useful if you use Bootstrap:
{% extends 'form_div_layout.html.twig' %}
{% block field_row %}
{% spaceless %}
{% set field_row_classes = ['control-group'] %}
{% if errors|length > 0 %}
{% set field_row_classes = field_row_classes|merge(['error']) %}
{% endif %}
<div class="{{ field_row_classes|join(' ') }}">
{{ form_label(form, label|default(null)) }}
<div class="controls">
{{ form_widget(form, { 'attr' : attr|default({}) }) }}
{{ form_errors(form) }}
{% if help is defined %}
<p class="help-block">{{ help }}</p>
{% endif %}
</div>
</div>
{% endspaceless %}
{% endblock field_row %}
The difference here is that I'm calling form_widget with the attr array (if it was specified, defaults to {})
Now you can set up your form as normal but pass through a custom class:
{{ form_row(myentity.myproperty, { 'label' : 'mylabel', 'attr' : { 'class' : 'myclass' }}) }}
This post need an update !
Since Symfony 4.3, the row_attr option permits to add attributes (and so, some class). Let's check those links :
Here :
https://symfony.com/blog/new-in-symfony-4-3-more-form-improvements#row-attributes-in-form-themes
or more specifically : https://symfony.com/doc/current/reference/forms/types/form.html#row-attr
I use this code to configure bootstrap in symfony
{% block field_row %}
{% spaceless %}
<div class="control-group {% if errors|length > 0 %}error{% endif %}">
{{ form_label(form, label, { 'attr': { 'class': 'control-label' } }) }}
<div class="controls">
{{ form_widget(form, { 'attr' : attr|default({}) }) }}
{{ form_errors(form) }}
</div>
</div>
{% endspaceless %}
{% endblock field_row %}
The easiest way to accomplish this without overwriting blocks is this:
{% set attr = {'class' : form.myElement.vars.attr.class ~ ' addedClasses...', 'style' : form.myElement.vars.attr.style ~ '; addedStyles...'} %}
{{- form_row(form.myElement, {'attr' : attr}) -}}

Resources