Symfony Form Theming: Override country choice option template - php

I have a form that renders a country select like this:
<div class="form-group">
<label for="form[country]" class="its--col-sm-2 control-label">{{ form_label(form.country) }}</label>
<div class="its--col-sm-10">
{{ form_widget(form.country, { 'attr':{'id': 'countryForm', 'class': 'form-control'} }) }}
</div>
</div>
The problem comes with AOTranslationBundle.
It's a great bundle. Registers in db all translations that are being rendered in your view and show them in the toolbar for translation.
Then, symfony's country choice tries to translate all countries that Symfony\Component\Intl\Intl::getRegionBundle()->getCountryNames() returns.
I solved this overriding choice_widget_options
{% form_theme form _self %}
{%- block choice_widget_options -%}
{% for group_label, choice in options %}
<option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.label }}</option>
{% endfor %}
{%- endblock choice_widget_options -%}
My question is... How can i override just country select options and not other select options?

You need to override for that particular field only.
You can try this approach.
Customize individual field

Related

Remove percent sign on a percent field type

I've been googling around but I couldnt find the way to remove the percent sign that the Form Component (Symfony) adds to the percent field type when rendering a form. I've found something related to redefined the percent widget but I couldn't get it how this works, neither where to change it.
This is what I found:
You can overwrite the percent_widget block from the default layout to
something like this:
{% block percent_widget %}
{% spaceless %}
{% set type = type|default('text') %}
{{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock percent_widget %}
My current rendering code inside the template is:
<div class="form-group">
{{ form_label(edit_form.discountRate, 'Discount', {'label_attr':{'class':'col-sm-2 control-label'}}) }}
<div class="col-sm-10">
<div class="input-group">
{{ form_widget(edit_form.discountRate, {'attr': {'class':'form-control'}}) }}
<div class="input-group-addon">%</div>
</div>
</div>
</div>
PD: Using the input-group class from boootstrap 3, I append that percent sign the way I like to render it, but how I delete the one that appends Symfony?
You have to override the default form theme of symfony 2.
First, open your app/config/config.yml file, and edit the twig configuration to have something like this :
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
form:
resources:
- YourBundleName:Form:my-form-theme.html.twig
(Its the form.resources part which is important). This configuration will tell Symfony 2 to use your custom theme.
You can also use {% form_theme form 'YourBundleName:Form:my-form-theme.html.twig' %} in your template if you don't want to add something in the config file, but I don't like to add this line in all my forms so I prefer to add it in global configuration.
Now you have to create a file src/YourBundlePath/Resources/views/Form/my-form-theme.html.twig with the following content :
{% extends 'form_div_layout.html.twig' %}
{% block percent_widget -%}
{% set type = type|default('text') %}
{{- block('form_widget_simple') -}}
{%- endblock percent_widget %}
And this should work.
If you open the theme file of Symfony 2 (/vendor/symfony/symfony/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig) you can see that there is :
{% block percent_widget -%}
{% set type = type|default('text') %}
{{- block('form_widget_simple') -}} %
{%- endblock percent_widget %}
I removed the "%" on the 3d line in the override.
Regards
You cant remove it, its one of cons of symfony form % char is hardcoded
{% block percent_widget -%}
{% set type = type|default('text') %}
{{- block('form_widget_simple') -}} %
{%- endblock percent_widget %}
You can write your own block, where You will remove %
You just have to override the form theme in the template. There are several ways to do it.
I'm going to use the quickest.
Your template would end up like this:
{% form_theme edit_form _self %}
{% block percent_widget %}
{% spaceless %}
{% set type = type|default('text') %}
{{ block('form_widget_simple') }}
{% endspaceless %}
{% endblock percent_widget %}
<div class="form-group">
{{ form_label(edit_form.discountRate, 'Discount', {'label_attr':{'class':'col-sm-2 control-label'}}) }}
<div class="col-sm-10">
<div class="input-group">
{{ form_widget(edit_form.discountRate, {'attr': {'class':'form-control'}}) }}
<div class="input-group-addon">%</div>
</div>
</div>
</div>
Well no need to rewrite templates, the idea is to make a front removal with jQuery/JS. Most of the time your input is embedded in a div, and twig is generating something you like this :
<div class="a">
<input ...>
%
</div>
'%' text can be accessed and removed with native JS lastChild/removeChild functions :
$('.a').removeChild($('.a').lastChild) (jQuery/JS mix)
document.getElementsByClassname(a).removeChild(document.getElementsByClassname(a).lastChild) (plain vanilla JS)

Cannot override form_widget and form_widget_compound

I think that it is a bug. But maybe someone can help me to solve my problem.
I have overridden form theme in twig template by next code:
{% form_theme form 'path_to_my_fields_template.html.twig' %}
Also I have overridden some of the form fields:
{% form_theme form.some_field 'path_to_another_fields_template.html.twig' %}
{% form_theme form.some_another_field 'path_to_another_fields_template.html.twig' %}
Then I overrode form_widget_simple in another file and included it in path_to_another_fields_template.html.twig, path_to_my_fields_template.html.twig using use twig-statement.
It works fine. But when I want to override form_widget_compound or form_widget it cannot be overridden and there are no errors, I see just form_widget_compound (applied to my form field) that declared in https://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
path_to_my_fields_template.html.twig:
{% use 'path_to_template_where_is_form_widget_simple.html.twig' %}
{% block form_row %}
{% spaceless %}
<tr>
{{ form_label(form) }}
{% set span_class = ('field ' ~ span_class|default(''))|trim %}
<td><span class="{{ span_class }}">{{ form_widget(form, {'attr': {'class': 'inner' }}) }}</span></td>
</tr>
{% endspaceless %}
{% endblock form_row %}
In the most cases form_widget generate form view with form_widget_simple and I'm happy. But when I have some related entities in my forms (compound field) all is bad.
Thanks in advance.

Shortcuts with Symfony2 Twig forms : form_widget

I would like to replace:
{{ form_errors(form.name) }}
{{ form_widget(form.name, { 'attr': {'placeholder': 'Nom'} }) }}
By:
{{ form.name|field('Nom') }}
How could I do that? I tried to do it in a Twig extension but I don't have access to the form_widget function.
Edit: I could do it with the form.name properties (that include the parent form) but I would repeat symfony code, it would be a very ugly big hack
Makes more sense if you ask me to move the attr to your form class:
class SomeForm extends AbstractType {
//.....
$builder->add('name', 'text', array('attr' => array('placeholder'=>'Nom')));
}
Since i guess you need some custom rendering for some of your fields you can check:
http://symfony.com/doc/2.0/cookbook/form/form_customization.html#how-to-customize-an-individual-field
You could also create a new type and customize it as explained here:
http://symfony.com/doc/2.0/cookbook/form/form_customization.html#what-are-form-themes
You could even change the default way of rendering and ask symfony to render your placeholder tag by default using the field's label string (the details of enabling the form theme globally are covered by the link referenced above):
{% block text_widget %}
{% set type = type|default('text') %}
<input type="text" {{ block('widget_attributes') }} value="{{ value }}" />
{% endblock field_widget %}
{% block widget_attributes %}
{% spaceless %}
{% for attrname,attrvalue in attr %}{{attrname}}="{{attrvalue}}" {% endfor %} placeholder="{{ label|trans }}"
{% endspaceless %}
{% endblock widget_attributes %}
{% block form_row %}
{% spaceless %}
<div class="my-class">
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
So you would limit yourself to a form_row(form.name) using the theming that symfony provides.
Symfony's aproach looks "very" DRY/DIE to me.
Hope it helps.

How to render input inside label in Symfony2 with Twig

I try to create a custom form theme for my project where I want to render all checkbox fields INSIDE the label like:
<label><input type="checkbox" /><label>
I've found out that I have to change the choice_widget_expanded block for this:
{% block choice_widget_expanded %}
{% spaceless %}
<div {{ block('widget_container_attributes') }}>
{% for child in form %}
{{ form_widget(child) }}
{{ form_label(child) }}
{% endfor %}
</div>
{% endspaceless %}
{% endblock choice_widget_expanded %}
The problem is, when I copy the content of the form_label block into the container instead of calling form_label(child), I don't really see how the block accesses the variable passed(which was child when I called the function), and how to call the form_widget function in the form_label block:
{% block form_label %}
<label>{{ form_widget(?? what to put here??) }}</label>
{% endblock form_label %}
Also, if I create a block with a different name, like "form_label_extra" and try to call it, it throws an error, because it's not a registered twig function.
Does anyone know how this variables are passed between the form blocks, and how to achieve my goal?
I did the same modifying the following block
{% block checkbox_widget %}
{% spaceless %}
<label class="button i_clear">
<input type="checkbox"
{{ block('widget_attributes') }}
{% if value is defined %} value="{{ value }}"{% endif %}
{% if checked %} checked="checked"{% endif %} />
<span>{{ label }}</span>
</label>
{% endspaceless %}
{% endblock checkbox_widget %}
You will still need to remove the original label, you can modify it with javascript, hide it with css or modify the template so it renders conditionally, whatever is best for you.
This question might also help: Symfony2 - How to put label and input for checkboxes/radios in a same line?

How to get form variables in custom form field in symfony2

I have this custom form field
{# src/Acme/DemoBundle/Resources/views/Form/fields.html.twig #}
{% block gender_widget %}
{% spaceless %}
{% if expanded %}
<ul {{ block('widget_container_attributes') }}>
{% for child in form %}
<li>
{{ form_widget(child) }}
{{ form_label(child) }}
</li>
{% endfor %}
</ul>
{% else %}
{# just let the choice widget render the select tag #}
{{ block('choice_widget') }}
{% endif %}
{% endspaceless %}
{% endblock %}
This renders the checkboxes. But i am not able to find how can i get the value of checkbox
i.e child.form.value is not working.
Suppose i have entities which is named as tasks in the form.
how can i get the value of the taskid.
something like
child.form.vars.task.id
It seems to be in {{ choice.value }}
Have a look at this to see how the inheritance works.
<option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice.label|trans({}, translation_domain) }}</option>

Categories