setting a placeholder attribute with translation in Symfony2 form input - symfony

I am using FOSUserBundle for managing my users. In order to register user, I reused the form of the bundle which meets my needs. Nevertheless, I needed to set some attributes of my fields. This is was done easyly by twig like this:
{{ form_widget(form.username, { 'attr': {'class': "span12",
'placeholder': "Username"} }) }}
Now, my goal is to make automatic translation on my placeholder, so I proposed this code:
{{ form_widget(form.username, { 'attr': {'class': "span12",
'placeholder': "{{'security.login.usernameplaceholder'|trans}}"} }) }}
This previous code produced an input with placeholder value equal to {{'security.login.usernameplaceholder'|trans}}
To get rid of this problem, I tried to set variable for that but symfony generated an error!!!
{% set usernameplaceholder = {{'security.login.usernameplaceholder'|trans}} %}
{{ form_widget(form.username, { 'attr': {'class': "span12",
'placeholder': usernameplaceholder} }) }}
Is there any proposition to solve this problem?
Thanks,

In Twig you shouldn't put {{ within {{ (same for {%); think of it as the php tag.
The following should work
{% set usernameplaceholder = 'security.login.usernameplaceholder'|trans %}
{{ form_widget(form.username, { 'attr': {'class': "span12",
'placeholder': usernameplaceholder} }) }}
OR
{{ form_widget(form.username, { 'attr': {'class': "span12",
'placeholder': 'security.login.usernameplaceholder'|trans} }) }}

For Symfony 3.x, 4.x
Another way to add placeholders (or any attributes for that matter) is by passing an options-array to the form $builder containing another Array attr with attributes as key-value pairs.
// The parameters are column name, form-type and options-array respectively.
$builder->add('field', null, array(
'attr' => array(
'placeholder' => 'support.contact.titleplaceholder'
)
));

You can translate this way as well (Using symfony4) in twig:
In a form placeholder wich would be written like this:
{'attr':{'placeholder': "Text to translate"}}
As for a placeholder in html wich would be written like this, you can translate this way:
<input placeholder="{{"Text to translate"|trans }}">

If you want to set the placeholder in the form-type (and not in the template) you must the placeholder inside the attr option. For example:
->add('search', TextType::class, ['attr' => ['placeholder' => 'form.custom.placeholder']])
To have the placeholder then translated in the background, you must adjust the form-theme.
In our case we wanted to trigger automatic translation only if the translation_domain is set explicitly in the form-type. This is how we achieved automatic translation:
{% block form_widget_simple -%}
....
{% if attr.placeholder|default and translation_domain|default %}
{%- set attr = attr|merge({placeholder: (attr.placeholder|trans({}, translation_domain))|trim}) -%}
{% endif %}
....
{{- parent() -}}
{%- endblock form_widget_simple %}
If you want to always trigger automatic translation. This should work:
{% block form_widget_simple -%}
....
{%- set attr = attr|merge({placeholder: (attr.placeholder|default|trans({}, translation_domain))|trim}) -%}
....
{{- parent() -}}
{%- endblock form_widget_simple %}

You can also add it to your form definition like this:
$builder
->add('information', 'textarea', array(
'label' => false,
'required' => true,
'constraints' => [
new NotBlank()
],
'attr' => [
'placeholder' => 'support.contact.titleplaceholder'
]
));

Related

Can you create something like "pre-labels" in a Symfony Form?

Is there a way to make something like Pre-Label in a Symfony Form? I want to format it differently than the normal label. I already tried it with HTML-injection in the normal label-option, like this:
$form->add('answer', TextAreaType::class, [
'label' => '<span>'.$data->category.'</span>'.$data->description
]);
But this doesn't work. Does someone else has an idea?
I found something like a workaround:
{% for question in question %}
<h1>{{ question.vars["value"].question.category.name }}</h1>
{{ question.vars["value"].question.description }}
{{ form_errors(question) }}
{{ form_widget(question, { 'attr': { 'class': 'form-control' }}) }}
{% endfor %}

Render choice options separately

I have researched quite a bit and also read the documentation but this thing remains unanswered.
I want to render choice-options separately in twig and a {%for%} loop doesn't seem to work.
Here's the situation:
I have 3 radio buttons which are supplemented with 3 different blocks of html each (therefore I cannot do a loop over the segments as they are different).
Form-Extract (form 'payment'):
array(
'choices' => array(
'paypal' => 'payment.method.paypal',
'bank' => 'payment.method.bank',
'check' => /** #Ignore */
),
'label' => 'payment.method',
'expanded' => 'true',
How could I access the different choice options in twig? I have tried
{{ form_widget(form.payment.method[bank]) }}
and also
{{ form_widget(form.payment.method.bank) }}
Thanks so much for your help.
Stefffen
You might want do it this way:
{% for method in form.payment %}
{% if method.vars.value == "paypal" %}
#Render it in a paypal awesome way
{{ form_widget(method) }}
{{ form_label(method) }}
{% else if method.vars.value == "bank" %}
#Render it in a bank awesome way
{{ form_widget(method) }}
{{ form_label(method) }}
{% endif %}
{% endfor %}
Hope it helps

Printing all errors in one go within twig

I want to print all errors in one go for all the fields however {{ form_errors(form) }} doesn't print anything so because of that I have to use if not form.vars.valid statement to print errors however all the individual error messages are being wrapped within <ul><li>Message</li></ul> which is annoying. I know that 'error_bubbling' => true solves the issue but creates another issue which is making field borders red.
How can I solve this issue? I simply want to print error without tags.
Note: I can use {{ form_errors(form.name)|striptags }} but it adds overheads cos my form is massive.
FORM TYPE
class BrandsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->setAction($options['action'])
->setMethod('POST')
->add('name', 'text', array('label' => 'Name'))
->add('button', 'submit', array('label' => 'Submit'))
;
}
}
TWIG
{% extends '::base.html.twig' %}
{% block body %}
{{ form_start(form, {attr: {novalidate:'novalidate'}}) }}
{% if not form.vars.valid %}
<div class="global_form_errors">
{{ form_errors(form.name) }}
{{ form_errors(form.origin) }}
</div><br />
{% endif %}
<div>
{{ form_label(form.name) }}
{% if form.name.vars.errors|length != '' %}
{{ form_widget(form.name, { attr: {'class': 'field_red_border'} }) }}
{% else %}
{{ form_widget(form.name) }}
{% endif %}
</div>
<div>
{{ form_widget(form.button) }}
</div>
{{ form_end(form) }}
{% endblock %}
Customize the field template
You can apply a form template to your form, check this documentation at Form Theming chapter.
If you prefer theming the field directly in your template, check the gray box in this documentation at the Global Form Theming chapter.
Check this documentation for more form customization.
Pass the errors to the template
When you submit the form, your code will call this method $form->handleRequest($request); which will check if the user input properly the data.
Based on the documentation of the Form class you can get a list of errors by calling $form->getErrors(). The variable $form is an instance of the Form class and not the FormView class. You may want to enable error bubbling.
Now that you know how to get the errors you can pass them as a variable to your template.

Directly access a form field's value when overriding widget in a twig template

What I want to do is get variables stored in form view.
{% form_theme edit_form _self %}
{% block field_widget %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{# MY CODE #}
{% if type == "file" %}
<a class="BOpreview" href="{# NEED TO REPLACE VAR HERE #}">Aperçu</a>
{% endif %}
{# MY ATTEMPT #}
{{ form.title.get('value') }}
{{ form.vars.value.url }}
{% endspaceless %}
{% endblock field_widget %}
My form has properties like url, title, etc and I am trying to access them here to use it in the field widget block.
I searched for it and came on https://groups.google.com/forum/?fromgroups=#!topic/symfony2/onor9uFte9E that suggested:
{{ form.title.get('value') }}
{{ form.vars.value.url }}
which didn't work for me.
Note: If I do a var_dump on $form->createView() in my controller, I get:
object(Symfony\Component\Form\FormView)[331]
private 'vars' =>
array (size=15)
'value' =>
object(Panasonic\TestEtAvisBundle\Entity\Product)[168]
protected 'reviewArray' =>
object(Doctrine\ORM\PersistentCollection)[234]
...
protected 'testArray' =>
object(Doctrine\ORM\PersistentCollection)[221]
...
protected 'fbshareArray' =>
object(Doctrine\ORM\PersistentCollection)[317]
...
private 'id' => int 2
private 'name' => string 'Nom du produit' (length=14)
private 'title' => string '<span>Titre </span>' (length=19)
private 'image' => string 'bundles/testetavis/uploads/product/0d9d9550.png' (length=47)
private 'fbImage' => string 'bundles/testetavis/uploads/product/facebook//product_e928cd96.jpg' (length=65)
private 'description' => string '<span>Descriptif </span>' (length=24)
private 'url' => string 'http://www.google.com' (length=21)
private 'creationDate' =>
object(DateTime)[210]
...
private 'modificationDate' =>
object(DateTime)[209]
...
private 'isDeleted' => int 0
'attr' =>
array (size=0)
empty
'form' =>
&object(Symfony\Component\Form\FormView)[331]
'id' => string 'panasonic_testetavisbundle_producttype' (length=38)
'name' => string 'panasonic_testetavisbundle_producttype' (length=38)
'full_name' => string 'panasonic_testetavisbundle_producttype' (length=38)
I want to access that url for instance but can't seem to be able to do it after many variations. Including use of {{ value }}, {{ value.url }}
But inspite of vars, I can do {{ full_name }} and get panasonic_testetavisbundle_producttype.
Any ideas?
Edit2: I found out the real problem...
Edit3: Seeing that this question is quite popular I decided to clarify on what I attempted to do in case it helps someone in the same situation. If you rely strictly on what the question asks, as I stated from my research and that Besnik supported are indeed correct.
Now what I wanted to do is for every input type file, get url from object used to render form and append a preview link, using retrieved url, beside the input type file.
If you try to get the form var of an input type "file" like this "{{ form.vars.value.url }}" in my code, this doesn't work since, if I recall correctly, you receive a token instead of the url stored inside the object.
You can access the current data of your form via form.vars.value:
{{ form.vars.value.title }}
See Symfony2 Forms documentation: http://symfony.com/doc/current/book/forms.html#rendering-a-form-in-a-template
Dump vars by using dump function:
{{ dump(form.vars.value) }}
If you are using subforms or want to have a value of a specific field:
{{ form.FIELD.vars.VALUE }}
You can access values of the parent parent from a widget block using form.parent.vars
For example, we want to render the value from a type text field called primerNombre we will need
{{ form.vars.value.primerNombre }}
If we wanted to render the name of one of the children we will need
{% for hijo in form.hijos %}
<td><div align="left">{{ form_widget(hijo.vars.value.primerNombre) }}</div></td>
{% endfor %}
Good luck!
In Symfony > 3 you may use:
form.vars.value.Entity.someValue
Edit2:
Finally, I was indeed getting the value of the current row in {{ value }} here:
{% block field_widget %}
{% spaceless %}
{% set type = type|default('text') %}
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ **value** }}" {% endif %}/>
{# MY CODE #}
{% if type == "file" %}
<a class="BOpreview" href="{{ value }}">Aperçu</a>
{% endif %}
{% endspaceless %}
{% endblock field_widget %}
But in my case I get a token instead of the value since I am using input type file. This is due to a security measure in Symfony2.

Link in form label using route

In my registration form i have a checkbox "I accept the terms", and want to link the word "terms" to my terms page.
Is there a way to add a link to a form label, using a route? (preferably without injecting the container in the form)
As the solution above somehow didn't work for me I solved it using the solution suggested here: https://gist.github.com/marijn/4137467
OK, so here i how I did it:
{% set terms_link %}<a title="{% trans %}Read the General Terms and Conditions{% endtrans %}" href="{{ path('get_general_terms_and_conditions') }}">{% trans %}General Terms and Conditions{% endtrans %}</a>{% endset %}
{% set general_terms_and_conditions %}{{ 'I have read and accept the %general_terms_and_conditions%.'|trans({ '%general_terms_and_conditions%': terms_link })|raw }}{% endset %}
<div>
{{ form_errors(form.acceptGeneralTermsAndConditions) }}
{{ form_widget(form.acceptGeneralTermsAndConditions) }}
<label for="{{ form.acceptGeneralTermsAndConditions.vars.id }}">{{ general_terms_and_conditions|raw }}</label>
</div>
The best way is to overwrite the twig block used to render that specific label.
First, check the form fragment naming section of the docs. Then create a new block in your form template with the the appropriate name. Don't forget to tell twig to use it:
{% form_theme form _self %}
For the next step check the default form_label block.
You'll probably only need a portion of it, something like this (I'm leaving the default block name here):
{% block form_label %}
{% spaceless %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ label|trans({}, translation_domain) }}
</label>
{% endspaceless %}
{% endblock %}
As an option, you can do so:
->add('approve', CheckboxType::class, [
'label' => 'Text part without link',
'help' => 'And download it',
'help_html' => true,
])
In Symfony 5.1 there are new form improvements.
HTML contents are allowed in form labels!
HTML contents are escaped by default in form labels for security reasons. The new label_html boolean option allows a form field to include HTML contents in their labels, which is useful to display icons inside buttons, links and some formatting in checkbox/radiobutton labels, etc.
// src/Form/Type/TaskType.php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('save', SubmitType::class, [
'label' => ' Save',
'label_html' => true,
])
;
}
}
In your case you can set form label directly from template and pass the route there.
{{ form_widget(form.acceptTermsAndConditions, {
label: '' ~ "I accept ..."|trans ~ '',
label_html: true
})
}}
My solution was another:
form:
$builder
->add(
'agree_to_rules',
'checkbox',
[
'required' => true,
'label' => 'i_agree_to'
]
);
And html:
<span style="display:inline-block">
{{ form_widget(form.agree_to_rules) }}
</span>
<span style="display:inline-block">
rules
</span>
And looks the same :)
A very simple way to do it would be
{{ form_widget(form.terms, { 'label': 'I accept the terms and conditions' }) }}
You can also do this if you want to use translation
In your translation file for example messages.en.yml add
terms:
url: 'I accept the terms and conditions'
And in your view add
{{ form_widget(form.terms, { 'label': 'terms.url'|trans({'%url%': path('route_to_terms')}) }) }}

Resources