How to combine two string in twig? - twig

I want to do something like this:
{% set c=a+b %}
Where a and b are strings.
How can I do it?

The way to do it is:
{% set c = a ~ b %}

Use the "~" operator. This will concatenate your two strings. The "+" operator cannot be used to combine strings.
You would get this:
{% set c=a~b %}
More info:
The "+" operator: Adds two objects together (the operands are casted to numbers).

You can use:
{{ "Hello " ~ name ~ "!" }}

A clearer example for the {% block page %}...{% endblock %}:
{% block page %}
{% set page = page | merge({
"title" : branchName,
"description" : "This description has "~branchName~" as its title"
}) %}
{{ parent() }}
{% endblock %}
A clearer example for the {% block content %}...{% endblock %}:
{% block content %}
This is just a sample string for {{ branchName }} that needs no concatenation
{% endblock %}

Related

How to render HTML to a variable

I need to render a list of HTML elements with content and put it into a variable. How can I do this efficient in twig?
e.g. I need to render the post tracking URLs from an order which can have several shippings / parcels.
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
Instead of printing this directly into the output I like first to put this rendered output into a variable like
{% set output = ... %}
...
{{ output }}
How can I do this in twig?
Just the concatenate the html to the output variable. Keep in mind you'll need to define to the variable outside the for-loop in order to use it outside the loop.
{% set foo = '' %}
{% for i in 1..10 %}
{% set foo = foo ~ ''~i~'' %}
{% endfor %}
{{ foo|raw }}
demo
After long search I found a better more efficient way
you can use {% set var %} with {% endset %} as a whole output block. Means the whole output will be set to the variable. This makes the life much easier and readable.
e.g.
{% set trackingText %}
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
{% endset %}
...
{% if trackingText|trim is not empty %}
You can track the delivery by using the following URL:<br/>
{{ trackingText }}
<br/>
{% endif %}

Variable/Index within head of a loop

I have a for-loop within another for-loop and I would like the inner for-loop to go through the array test[INDEX] with [INDEX] being the index of the outer for-loop. I know I can get the loops index with the variable {{ loop.index() }}, however I do not know how to apply that within the head of my inner loop.
I've tried {% for x in test.{{ loop.index0 }} %}, but that throws me the error
Expected name or number.
Is there any way to do this?
In twig you can also use the array notation to get values from a variable
A note here is that the default loop.index is 1 indexed so you might want to use loop.index0 to get the correct offset
{% for f in foo %}
- {{ f }}: {{ bar[loop.index0] }}
{% endfor %}
As an alternative you can also get the key in the {% for key, value ... format
{% for key, value in foo %}
- {{ value }}: {{ bar[key] }}
{% endfor %}
demo
edit
As for you comment, you can succesfuly use this in any inner-loop, here is a more readable example
{% for country in countries %}
{{ country }}:
{% if cities[loop.index0]|default %}
<ul>
{% for city in cities[loop.index0] %}
<li>{{ city }}</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
demo

Twig strip textarea and create array

I'm trying to strip some text from a value and afterwards create an array from it with the stripped values.
I'm having troubles to strip the text value.
I can only do this on the frontend since I have no access to the backend (SaaS platform)
In below example value.value (originally a textarea) returns the following text:
[185047078]1x something - Type 1
[415533322]1x something - something
[152890667]1x something 500x500 mm
I want to strip the text so I have [185047078], [415533322], [152890667] left or without the brackets.
Normally in JS you would do something like:
hide_ids = txt.match(/[^\]\[]+(?=\])/g)
However it need to be done in Twig.
Afterwards I want to push the values into an array hide_ids.
{% set hide_ids = [] %}
{% if product.custom %}
{% for custom in product.custom %}
{% if 'Some title' in custom.title %}
{% for value in custom.values %}
{% set hide_this_id = value.value %}
{% if hide_this_id matches '{/[^\]\[]+(?=\])/g}' %}
{% set hide_ids = hide_ids | merge([hide_this_id]) %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% set hidden = false %}
{% if id in hide_ids %}
{% set hidden = true %}
{% endif %}
What is the equivalent of match in Twig? I also tried replace but I just can't get that text stripped.
Any help greatly appreciated!
You could go with some simple string functions.
{% for id in ids %}
{{ id | split(']', 2)[0] | replace({'[': '',}) }}
{% endfor %}
demo
split is the explode of twig. This will separate your string in chased based on the ] character. The 2nd parameter (2) ensures there will only be maximum 2 parts in the array.
replace is just str_replace
If you wanted to solve this with regex you would either need to write a function/filter with preg_match or install an extension like this

Twig replace part of string with chosen character

I want to replace part of string characters with asterisks in Twig.
For example:
SomePartlyVisibleStringHere
I want to change every letter after 4th in this string with asterisks, to have result like that:
Some*********************
Is it possible to do without defining new Twig helper?
You could make a macro (a function in Twig) and call it whenever you want to do this.
{% macro redact(topSecret) %}
{% set length = topSecret|length - 4 %}
{{ topSecret|slice(0, 3) }}{% for i in 0..length %}*{% endfor %}
{% endmacro %}
{# You have to import from _self if the macro is declared in the same file. #}
{% import _self as sharpie %}
{{ sharpie.redact('Top secret information') }}
{# => Top******************* #}
Example: https://twigfiddle.com/aobt8s
This worked for me:
{% set string = 'SomePartlyVisibleStringHere' %}
{% set starCount = string|length - 4 %}
{{ string[:4] }}{% for i in 1..starCount %}*{% endfor %}
If you have to do it more than once I would suggest making a custom filter, then you can just do:
{% set string = 'SomePartlyVisibleStringHere' %}
{{ string|customFilterName }}

Twig: in_array or similar possible within if statement?

I am using Twig as templating engine and I am really loving it. However, now I have run in a situation which definitely mustbe accomplishable in a simpler way than I have found.
What I have right now is this:
{% for myVar in someArray %}
{% set found = 0 %}
{% for id, data in someOtherArray %}
{% if id == myVar %}
{{ myVar }} exists within someOtherArray.
{% set found = 1 %}
{% endif %}
{% endfor %}
{% if found == 0 %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
What I am looking for is something more like this:
{% for myVar in someArray %}
{% if myVar is in_array(array_keys(someOtherArray)) %}
{{ myVar }} exists within someOtherArray.
{% else %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
Is there a way to accomplish this which I haven't seen yet?
If I need to create my own extension, how can I access myVar within the test function?
Thanks for your help!
You just have to change the second line of your second code-block from
{% if myVar is in_array(array_keys(someOtherArray)) %}
to
{% if myVar in someOtherArray|keys %}
in is the containment-operator and keys a filter that returns an arrays keys.
Just to clear some things up here. The answer that was accepted does not do the same as PHP in_array.
To do the same as PHP in_array use following expression:
{% if myVar in myArray %}
If you want to negate this you should use this:
{% if myVar not in myArray %}
Try this
{% if var in ['foo', 'bar', 'beer'] %}
...
{% endif %}
another example following #jake stayman:
{% for key, item in row.divs %}
{% if (key not in [1,2,9]) %} // eliminate element 1,2,9
<li>{{ item }}</li>
{% endif %}
{% endfor %}
Though The above answers are right, I found something more user-friendly approach while using ternary operator.
{{ attachment in item['Attachments'][0] ? 'y' : 'n' }}
If someone need to work through foreach then,
{% for attachment in attachments %}
{{ attachment in item['Attachments'][0] ? 'y' : 'n' }}
{% endfor %}
It should help you.
{% for user in users if user.active and user.id not 1 %}
{{ user.name }}
{% endfor %}
More info: http://twig.sensiolabs.org/doc/tags/for.html
Here's one to complete the answers with all the possibilities of Twig these days:
To achieve something like this:
{% for myVar in someArray %}
{% if myVar in someOtherArray|keys %}
{{ myVar }} exists within someOtherArray.
{% else %}
{{ myVar }} doesn't exist within someOtherArray.
{% endif %}
{% endfor %}
(https://twigfiddle.com/0b5crp)
You could also use array mapping and have the following one-liner:
(Twig >= 1.41 or >= 2.10 or any 3.x version)
{{ someArray|map(myVar => myVar ~ (myVar not in someOtherArray|keys ? ' doesn\'t') ~ ' exists within someOtherArray.')|join('\n') }}
Which outputs something quite similar.
Also see this Twig fiddle: https://twigfiddle.com/dlxj9g
{% if myVar in myArray %} without keys helps me

Resources