I would like to use the ternary operator of Twig but it shows me the HTML tags as text.
{{ (sender.firstName or sender.lastName) ? "<strong>#{sender.firstName} #{sender.lastName}</strong>" : '<strong>Unknown</strong>' }}
The result is <strong>My Name</strong> but it should be My Name.
You have to apply the raw as the output is not marked as safe when concatenating html with twig
{{ (sender.firstName or sender.lastName ? "<strong>#{sender.firstName} #{sender.lastName}</strong>" : "<strong>Unknown</strong>")|raw }}
demo
Related
I have a page where I need to show/print the same content twice. For this, I am using drupal_view.
{{ drupal_view('product_content', 'page_1', node.id) }}
This code works only for the first position and for the second position it doesn't work. What can be done so that the content shows up in both places?
Got the solution from the Drupal community:
When something is rendered, the render system remembers what has been
rendered and won't re-render that. Assign the render output to a twig
variable and print the variable twice:
> {% set product_content = drupal_view( ... )|render %}
> {{ product_content }}
> {{ product_content }}
I'm not able to find a equivalent of lcfirst php function in Twig, my need is to lower only the first letter of a word ?
If such function doesn't exist, what is the best way to do it ?
As discussed in this issue on Github, you could use:
{{ foo[:1]|lower ~ foo[1:] }}
See this working example.
Just add the function into twig by chaining it with a filter, e.g.
$twig->addFilter(new \Twig\TwigFilter('lcfirst', 'lcfirst'));
Then use it inside any twig template like
{{ string | lcfirst }}
You can use a capitalize filter:
{{ 'my first car'|capitalize }}
{# outputs 'My first car' #}
https://twig.symfony.com/doc/1.x/filters/capitalize.html
It seems easy, but I encounter a weird behavior.
In a twig file :
{% set my_html = 'Hello world' %}
{{- true is not same as(false) ? (true is same as(false) ? ('1'~my_html)|raw : ('2'~my_html)|raw) -}}
The printed part is ('2'~my_html)|raw and it works fine : I see a real link.
Output is :
2Hello world
Now, it works only because I apply the raw filter to ('1'~my_html)... Try this :
{% set my_html = 'Hello world' %}
{{- true is not same as(false) ? (true is same as(false) ? ('1'~my_html) : ('2'~my_html)|raw) -}}
And it will display : 2Hello world
I don't understand why I need to apply a filter on something else to get the expected result ? Is it a bug ?
This is a documented behavior of the raw filter. I quote the note from that page:
Be careful when using the raw filter inside expressions:
{% autoescape %}
{% set hello = '<strong>Hello</strong>' %}
{% set hola = '<strong>Hola</strong>' %}
{{ false ? '<strong>Hola</strong>' : hello|raw }}
does not render the same as
{{ false ? hola : hello|raw }}
but renders the same as
{{ (false ? hola : hello)|raw }} {% endautoescape %}
The first ternary statement is not escaped: hello is marked as being
safe and Twig does not escape static values (see escape). In the
second ternary statement, even if hello is marked as safe, hola
remains unsafe and so is the whole expression. The third ternary
statement is marked as safe and the result is not escaped.
And a comment on a github issue clarifies that the concatenation operator marks your string as unsafe. So in your case
{% set my_html = '<' %}
{# ('1'~my_html) is not safe, so the whole expression is not #}
{{ false
? ('1'~my_html)
: ('2'~my_html)|raw
}}
includes two strings: a safe one, ('2'~my_html)|raw) and an unsafe one, ('1'~my_html) (because it does not apply the raw filter), so as the note from raw documentation says, the whole expression stays unsafe and autoescaping is applied. But in the other case when both strings are marked safe, the whole expression becomes safe and the autoesaping is not applied:
{% set my_html = '<' %}
{# now both strings are safe, so is the whole expression #}
{{ false
? ('1'~my_html)|raw
: ('2'~my_html)|raw
}}
This is not a bug but, due to the fact the default settings of twig will autoescape variables.
You can read more about it in the documentation.
I have this in my template
{{ ad.title_de }}
Now I'm incorporating multiple languages, so 'title_de' has to change
I also have a variable 'tld' which is one of de, en , fr
So I'd like to have something like
{% if tld == 'fr' %}
{{ ad.title_fr }}
etc
Any ideas?
Try using the attribute function.
http://twig.sensiolabs.org/doc/functions/attribute.html
attribute(ad, 'content_'~tld) should work.
Try with this:
{{ ad["title_" ~ tld] }}
I want to achive this is twig:
{{ form_widget(form.orderItems.0.enabled) }}
{{ form_widget(form.orderItems.1.enabled) }}
{{ form_widget(form.orderItems.2.enabled) }}
....
but the number to be a variable.
I tried this:
{% set index = 0 %}
{{ form_widget(form.orderItems.index.enabled) }}
Error: Method "index" for object "Symfony\Component\Form\FormView" does not exist
and this:
{{ form_widget(form.orderItems.{{index}}.enabled) }}
Error: Expected name or number
and this:
{{ form_widget(form.orderItems.~index~.enabled) }}
Error: Expected name or number
It is possible to achieve this :(
Some digging suggests you use the 'attribute' function - see Accessing array values using array key from Twig.
I suppose that would be something like
form_widget(attribute(form.orderItems, index).enabled)
Unfortunately I can't easily test that at the moment, but it should get you on the right track.
I am solving the same problem now and getting "expected name or number error" when I want to access variable dynamically.
I can not find simple answer, how to dynamically replace some part of variable in twig.
But It works without first dot as was first comment here.
{{ form[othervariable value].vars.label }}
and NOT
{{ form.[value].name }}