multiple display of the same form_widget(form) - symfony

I would like to display a uniquely defined form_widget(form.myform) at several places in my code.
How could I do it?
When just put form_widget(form.myform) at different places in my code, only the first one is shown, all the following ones are ignored.
Thank you!

It is impossible by following reason: by default twig generates id for each form field considering following scheme - formTypeName_formTypeFieldName, and there could be only one element with such id at the same time.
EDIT:
You could try something like {{ form_widget(form.title, { 'id': 'my_custom_id' }) }} with different identeficators for same field, but those input still will have same names and to be frank I'm doesn't sure how it will be handled by symfony kernel.

Related

What is the purpose of "do" tag in twig

I have seen the twig documentation about do tag, but I don't understand its use/useful.
The docs says the follow:
The do tag works exactly like the regular variable expression ({{ ...
}}) just that it doesn't print anything:
and show an example:
{% do 1 + 2 %}
What to solve exactly this tag ?
Good question! I found a link on GitHub to when this was proposed which might add some further info:
Sometimes you want to do things, or call some stuff, and ignore the output. For example if you use a |shift filter to remove some data from an array, doing {{ arr|shift }} will output the removed item, which is not always desirable.
Of course it's possible to do {% set null = arr|shift %}, which won't
output anything, but it also looks weird.
The example in the docs is poor as it explains nothing at all, as you pointed out.

How to use substr with strstr in Twig

I'm working on a Symfony site which incorporates a scheduler, and on this scheduler there are tasks which have user's names on them. My client has requested that only the surname be shown but currently the database saves the name as a complete string named contactName.
I am currently using the following code in Twig to display the name:
schedule.user.contactName
I tried using the split command, which seemed to do what I want:
schedule.user.contactName|split(" ",1)
But this only returns an array, and I do not know how to take the surname from this.
Any help with this is appreciated - maybe there is an alternative way to do this?
Maybe you could try this:
schedule.user.contactName|split(' ', 2)|first
There are two ways I can think of:
Set the output of the split function as a new variable, and since it's an array, you should be able to get name[1], or maybe name.1 from it for the 2nd part (if it exists, and your customer is not 'Cher', 'Prince', or the like).
It's probably easier to do it in two parts like this, rather than trying to combine it to a single statement.
{% set nameParts = schedule.user.contactName|split(" ",1) %}
{{ nameParts[1]|default(schedule.user.contactName) }}
You can also perform the split within the entity - getContactNameSurname() that does the split in PHP code, and returns the 2nd part.

Drupal : Access values in field-collection with twig

In my Drupal project I'm unable to access values of a field-collection. I can output all values by using:
{{ item.content }}
But I'm not able to get deeper nested values, which are objects.
For example I would like to get the value «field_interpret».
This things don't work:
{{ item.content['#field_collection_item'] }}
{{ item.content.#field_collection_item }}
{{ item.content.field_collection_item }}
Thank you for help.
After several days of searching and testing I ended up with a plain old and dirty sql-query which I included in the preprocess_field function.
My problem was, that I don't found a way to access the elements in a field-collection and I had to make some calculation based on the field values.

TAPi18n: how to construct the key to be translated dynamically?

I'm trying to add a prefix to the keys to be translated. This is one of my attempts:
<label for="{{n}}">{{_ 'input_label_{{n}}' }}</label>
<input name="{{n}}" placeholder="{{_ 'input_placeholder_{{n}}' }}">
Obviously it does not work because you can't nest {{ ... }}'s.
I've also tried creating a helper:
{{tr 'input_label' n}}
tr: function(prefix, fieldName) {
return TAPi18next.t(prefix + '_' + fieldName);
}
But it comes back untranslated. I assume because I'm calling TAPi18n as a static and not an instance of it, but I don't know how else to do it.
These are just two of many attempts.
I will have hundreds of inputs, and I want to avoid sending all the translation keys to the input template, since it's redundant information. The key variations can easily be made by adding prefixes.
Can you think of any way to generate the key values dynamically?
Use the second approach, but with TAPi18n.__ rather than TAPi18next.t.
Unlike TAPi18next.t, TAPi18n.__ reactively updates when the user's language choice is changed and the language has finished downloading. I'm guessing the problem is that the language choice hasn't quite come through when the template is first rendered, so TAP18next.t returns the strings in the default language (English), and doesn't update when the language changes. Using TAPi18n.__ instead fixes this.

Symfony2: HTML inside translation message

In messages.en.yml, I have
confirmed: Congrats %username%, your account is now activated.
But I want to 'bold' username to example ... how can I made this ?
confirmed: Congrats <span class='bold'>%username%</span>, your account is now activated.
Of course I could use two sentence in this example like
first: Congrats
second: , your account ...
and inside twig use the html tag but this seems very dirty.
Update 2
In such cases, I started to use like this:
confirmed: Congrats %start_link%%username%%end_link%, your account is now activated
Since separation of concerns is maintained, this way is strongly recommended.
Update
In YAML, I have used translations like this without any problem:
trans.key: click here to continue
Although translations and design should be kept separated there are always some situations that you must use html tags inside translation files as it is also seen in huge projects like Facebook and Twitter.
In such situations, you can use XLIFF format which is being recommended by Symfony. Inside translation file:
<trans-unit id="1">
<source>confirmed</source>
<target>Congrats <![CDATA[<span class='bold'>%username%</span>]]> , your account is now activated.</target>
</trans-unit>
Twig's Raw Filter
I don't know if this was an option back in 2013 but when using translation, you can apply the raw twig filter having this translation string:
confirmed: Congrats <span class='bold'>%username%</span>,
your account is now activated.
And use it in twig like this:
{{ 'confirmed'|trans|raw }}
This will not escape the html inside the string and will display the username as bold.
Update: I haven't seen the comment the first time, but Rvanlaak had proposed the raw filter solution in the first place.
Security issues
Note that the content of those translation strings must not be user provided, because it could open up your application to XSS attacks. Using the raw filter allows JavaScript to be executed if a malicious user is able to input custom data into the translation strings (Community based translations for example)
Separation of concerns
Using the raw filter does not comply with separation of concerns as the content and styling are bound together. As Ferhad mentioned, using his method, separation of concern will be maintained. But in my case, I preferred using a simple raw filter. I felt that for my case, Ferhad's method was a bit overkill for me, though it would be more recommended his way
My approach is although still ugly, but at least respects the separation of concerns. Escape filter is used to escape a variable, making the final result is pretty safe from XSS, because all other sources considered to be hard-coded.
translations.yml
points: You have %num% points left.
template.html.twig
{% set pointsFormatted = '<span class="points">' ~ num | escape ~ '</span>' %}
{{ 'pages.score.points' | trans({'%num%' : pointsFormatted}) | raw }}
I've just found something out, you can use this in your YAML file:
mind: >
<i>Mind is a nice thing to have</i>
So this ">" sign in the first row achieves it. I think this would be the preferred way, better than handling the escapes etc in TWIG.
I've looked it up now and it is actually a YAML feature. Check here :)
Also, there's an earlier question with similar subject: How can I get YAML to ignore raw HTML in same file.
some yml:
dashboard:
hello: Hello <b>%username%</b>
+
{{ 'dashboard.hello'|trans({'%username%': app.user.username}, 'General') | raw }}
this | raw part worked for me
In my opinion, this is the best solution today:
'key'|trans({'%username%': '<strong>' ~ suspiciousVar|escape ~ '</strong>'})|raw
The only risk here is stored XSS in your translation files.
Holding HTML stuff in translations is wrong, because translators usually break it. But if you really need it:
Twig:
{% trans %}confirmed{% endtrans %}
Yaml translation file:
confirmed: 'Congrats <span class="bold">%username%</span>, your account is now activated.'
Discussion about this:
https://github.com/symfony/symfony/issues/2713
We could use separate twig snippets for different languages if situation requires heavy formatting differences. I wrote a little blog on this.
{# templates/translations/user_message.pl.html.twig #}
{{ 'msg.my_favourite_language_is' }}<b>{{ 'langnames.elfic_language' | trans | lower }}</b>!
{# templates/translations/user_message.en.html.twig #}
{{ 'msg.my_favourite_language_is' }}<i>{{ 'langnames.elfic_language' | trans | ucfirst }}</i>!
{# templates/pages/index.html.twig #}
{% set locale=app.request.locale[:2] %}
{% include 'translations/calculator_message.' ~ locale ~ '.html.twig' %}
Translation files are for translations, design and layout is part of the view layer (namely: template engine (twig)). You can split it into two pieces: congrats and account.activated.

Resources