Symony2 Form Templating Error - Variable "widget" does not exist - symfony

I am trying to alter the date_widget using symfony2 and twig. I would like to display just the year.
After reading Symfony 2 date input with only year selector and the symfony2 book chapter on templating forms I have copied the date_widget block into my template and am receiving the error:
Variable "widget" does not exist in bundle....
here is the code from my template:
{% extends '::base.html.twig' %}
{% block body %}
{% block date_widget %}
{% spaceless %}
{% if widget == 'single_text' %}
{{ block('field_widget') }}
{% else %}
<div {{ block('widget_container_attributes') }}>
{{ date_pattern|replace({
'{{ year }}': form_widget(form.year),
})|raw }}
</div>
{% endif %}
{% endspaceless %}
{% endblock date_widget %}
....print form (generated though app/console generate:crud)
{% endblock %}
Any Thoughts? Thanks!

put the date_widget block outside of the body block, and add the following code after the initial extends
{% form_theme form _self %}
now, your code should look like this
{% extends '::base.html.twig' %}
{% form_theme form _self %}
{% block body %}
....print form (generated though app/console generate:crud)
{% endblock %}
{% block date_widget %}
{% spaceless %}
{% if widget == 'single_text' %}
{{ block('field_widget') }}
{% else %}
<div {{ block('widget_container_attributes') }}>
{{ date_pattern|replace({
'{{ year }}': form_widget(form.year),
})|raw }}
</div>
{% endif %}
{% endspaceless %}
{% endblock date_widget %}
http://symfony.com/doc/current/book/forms.html#form-theming

Related

symfony's form_errors displays list item instead of just text

[ Symfony 4 ]
I've this template code in Symfony:
{{ form_widget(registrationForm.username, {'attr': {'class': 'form-control'}}) }}
{{ form_errors(registrationForm.username) }}
Instead of just displaying error text, it's generating a list item like this:
<ul><li> Username already exists </li></ul>
How to not have it generate this list item and just get the text?
I guess it is correct behavior, cause you can have multiple errors for one field for example "Username is too short" and "Field Username contains inappropriate characters", but to get only first error you can use:
{{ form_errors(registrationForm.username|first) }}
Or you can customize your form_errors rendering, first create file for form_errors, for example your_form/custom_form_errors.html.twig :
{% block form_errors %}
{% spaceless %}
<div class="error">{{ errors|first }}</div>
{% endspaceless %}
{% endblock %}
And after that include it to your view file:
{% form_theme form 'your_form/custom_form_errors.html.twig' %}
...
{{ form_errors(registrationForm.username) }}
just to extend #Andrii Filenko 's answer. You can modify the output the form_errors or any other form twig function pretty easily. it's called custom theming in Symfony.
Consider this:
// templates/register.html.twig
{% extends "base.html.twig" %}
{% form_theme registrationForm _self %}
{% block form_errors %}
{% spaceless %}
{% if errors|length > 0 %}
<ul class="changed list">
{% for error in errors %}
<li>{{ error.message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endspaceless %}
{% endblock form_errors %}
{% block body %}{% endblock %}
Output:
<ul class="changed list"><li> Username already exists </li></ul>

rendering forms and widget in Symfony2

I am developing a website and I would like to personalized how the forms are rendered.
My purpose is for each field I should achieve this structure
<div class="form-group">
<label for=":id">:LABEL</label>
<input type=":type" class="form-control" id=":id" />
</div>
In case of checkbox, the input must to appear first and without class atribute
The options for doing this are listed in Symfony Form Theming documentation.
In your form theme Twig file (normally app/Resources/views/form.html.twig) you should add something like this:
{% block form_row %}
{% spaceless %}
<div class="form-group">
{{ form_label(form) }}
{{ form_errors(form) }} {# Can remove this unless you want inline errors #}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
{% block form_widget_simple %}
{% spaceless %}
{% set type = type|default('text') %}
{% set attr = attr|merge({'class': (attr.class|default('') ~ ' form-control')|trim}) %}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock form_widget_simple %}
The Ryan answer has needed to add one more line like this:
{% form_theme form _self %}
{% block form_row %}
{% spaceless %}
<div class="form-group">
{{ form_label(form) }}
{{ form_errors(form) }} {# Can remove this unless you want inline errors #}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
{% block form_widget_simple %}
{% spaceless %}
{% set type = type|default('text') %}
{% set attr = attr|merge({'class': (attr.class|default('') ~ ' form-control')|trim}) %}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endspaceless %}
{% endblock form_widget_simple %}
as per symfony2 documentation How to customize Form Rendering the current template in which u want to make change , u will have to write the line
{% form_theme form _self %}
in the starting of any block overriding ..

How to show label for overrided checkbox in Symfony Twig

I've overrided the Twig template for my forms in my symfony application so that I could have more control over the labels for checkboxes.
However, I am having problems with the checkbox label.
Here is the code I overrided in my custom template file:
{# Labels #}
{% 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 %}
{% endif %}
{% if 'checkbox' not in block_prefixes %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>{{ label|trans({}, translation_domain) }}</label>
{% endif %}
{% endspaceless %}
{% endblock form_label %}
{# Checkboxes #}
{% block button_label %}{% endblock %}
{% 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 }}</label>
{% endspaceless %}
{% endblock checkbox_widget %}
It works fine but I can't get the label text node for checkboxes working.
When I have a checkbox it generates something like:
<label><input type="checkbox"/></label>
Where it should be:
<label><input type="checkbox"/>Label Here</label>
Any clue on how to make the label string apear after the checkbox?
Edit:
I came to a solution, that worked pretty fine, but I am not sure if it the best.
{% block form_row %}
{% spaceless %}
<div>
{{ form_errors(form) }}
{% if 'checkbox' in block_prefixes %}
{{ form_widget(form) }}
{{ form_label(form) }}
{% elseif 'radio' in block_prefixes %}
{{ form_widget(form) }}
{{ form_label(form) }}
{% else %}
{{ form_label(form) }}
{{ form_widget(form) }}
{% endif %}
</div>
{% endspaceless %}
{% endblock form_row %}
You can remove the label in {% block choice_widget %} to prevent it from appearing in the default spot.
{% block choice_widget %}
{% spaceless %}
{% if expanded %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }} {# HERE #}
{% endfor %}
</div>
{% else %}
//....
{% endspaceless %}
{% endblock choice_widget %}
If you do so, you would have to override the {% block radio_widget %} too. Otherwise it won't have a label.
<label for="{{ id }}"><input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />{{ label|trans }}</label>
You can then remove the {% if 'checkbox' not in block_prefixes %} line you put in {% block form_label %}.
It worked for me.
Symfony2 - How to put label and input for checkboxes/radios in a same line?
Edit :
it seems that they split the {% block choice_widget %} in 2.3.3. You have to edit the choice_expanded block now, and remove the label line as above.
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }} {# There #}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}

How to check if widget is a checkbox in twig

Im theming my forms i want dont show the label if the field is a checkbox
{% form_theme form with _self %}
{% block form_row %}
{% spaceless %}
<div class="mygroup">
{{form_label(form)}} # hide if checkbox
{{form_errors(form)}}
{{form_widget(form)}}
</div>
{% endspaceless %}
{% endblock %}
after a while i found solution in Google Group
{% block form_row %}
{% spaceless %}
<div class="mygroup">
{% if 'checkbox' not in form.vars.block_prefixes %}
{{form_label(form)}}
{% endif %}
{{form_errors(form)}}
{{form_widget(form)}}
</div>
{% endspaceless %}
{% endblock %}

Customization of a form widget in Symfony2/Twig

In my form template:
{% block field_label %}
{% spaceless %}
<label {{ block('widget_attributes') }}></label>
{% endspaceless %}
{% endblock %}
I need to add some extra class attributes and, of course, display the label (possibly translated). I've found that {{ block('widget_attributes') }} stores a string of attributes of the actual label.
Any chance to get an array type to easily modify it? Where i can find all block names to customize the appearance to fit my needs? Thanks for helping.
Nevermind Notepad++ helped me to find the file:
vendor\symfony\src\Symfony\Bridge\Twig\Resources\views
Three types of label defined:
{# Labels #}
{% block generic_label %}
{% spaceless %}
{% if required %}
{% set attr = attr|merge({'class': attr.class|default('') ~ ' required'}) %}
{% endif %}
<label{% for attrname,attrvalue in attr %} {{attrname}}="{{attrvalue}}"{% endfor %}>{{ label|trans }}</label>
{% endspaceless %}
{% endblock %}
{% block field_label %}
{% spaceless %}
{% set attr = attr|merge({'for': id}) %}
{{ block('generic_label') }}
{% endspaceless %}
{% endblock field_label %}
{% block form_label %}
{% spaceless %}
{{ block('generic_label') }}
{% endspaceless %}
{% endblock form_label %}

Resources