Nested for - in loop - twig

I have a multidimensionnal PHP array sent to Twig (with Symfony 4).
I want to create a loop in a loop with nested for in, as i can do in PHP with nested foreach.
I have this type of PHP array :
globalArray[0]['title'] = "title 1"
globalArray[0]['contents'][0]['text'] = "sub element 1.1"
globalArray[0]['contents'][1]['text'] = "sub element 1.2"
globalArray[1]['title'] = "title 2"
globalArray[1]['contents'][0]['text'] = "sub element 2.1"
globalArray[1]['contents'][1]['text'] = "sub element 2.2"
...
I try with twig, that :
{% for element in globalArray %}
{{ element.title }}<br />
{% for subElement in element.contents %}
- {{ subElement.text }}<br />
{% endfor %}
{% endfor %}
Titles of my elements are displayed well
but any sub-element are displayed (and any "-" are displayed too, as if it does'nt enter in my second for-in)
How can i do because i don't undestand what is happening.
Any ideas ?
Thans a lots!
[EDIT]
when i dump() the "element" in my first for-in loop, i view well the "contents" subelements
when i dump() the "subElement" in my second for-in, any dump() zre visible (it seems not enter in the second for-in).

Related

If statement with string length check

I'm trying to check if a string is empty in a twig template but I don't understand this behaviour. I want to show a textarea element when the condition is met. Here's the code:
{% if item.payload.customizationText|length == 0 %}
<textarea class="customization-text">{{ item.payload.customizationText|trim }}</textarea>
{% endif %}
It always shows the textarea, whether the string has something in it or not. Am I missing something?
It's in shopware 6 by the way and the dump() fuction throws an error because it's undefined.
Also, this expression just outputs the string. Is the length expression not available?
{{ item.payload.customizationText|length }}
I believe there is a mistake in the question. It does not make sense to print the variable, only if it is empty.
If you want to show the text area in case the customizationText has some contents, you should use this:
{% if item.payload.customizationText|trim|length %}
<textarea class="customization-text">{{ item.payload.customizationText|trim }}</textarea>
{% endif %}
https://twigfiddle.com/nmk2kq/4
You can try it.
{% if item.payload.customizationText is defined and item.payload.customizationText is empty %}
<textarea class="customization-text">{{ item.payload.customizationText|trim }}</textarea>
{% endif %}

Problem creating JSON outuput in Twig Template

I'm learning to use the Craft CMS, which uses Twig templating. I'm trying to output a JSON object in Twig, but instead of 2 items in the JSON I'm getting info about a single item.
Here is my code:
{% set newsitems = craft.entries.section('newsitems').orderBy('PostDate desc').limit(100) %}
{% set response = [] %}
{% for newsitem in newsitems %}
{{ 'Here' }}
{% set response = response|merge({'type':0, 'id':newsitem.id, 'link':newsitem.sourceLink}) %}
{% endfor %}
{{ response|json_encode() }}
And here is the output I get:
Here Here {"type":0,"id":"25","link":"https:\/\/gadgets.ndtv.com"}
As can be seen, the loop executes two times ('Here' is printed 2 times) but there is only one item in the JSON array which is printed.
Am I missing something basic? Any help would be appreciated. Thanks in advance.
Twig's merge filter uses array_merge in the background.
The manual states the following
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
This is what is happening to your output, in the first iteration you've create an associative array with the key: type, id, link. In the x'th iteration you are just overwriting the values stored in said keys. The solution is also stated in the manual, numeric indices will be appended to the array instead of overwriting it.
In twig you would solve it as this:
{% set response = [] %}
{% for newsitem in newsitems %}
{% set response = response|merge([{ 'type': 0, 'id': newsitem.id, 'source': newsitem.source,},]) %}
{% endfor %}
{{ response|json_encode|raw }}
demo

How can I check the value of a dropdown menu in craft cms / twig?

I have a dropdown menu with 2 options
Ordered
Unordered
I want to check if the value is Unordered or Ordered
{% set viewModel = {
cards: content['cards'] ?? [],
cardListType: content.cardListType ?? ''
} %}
{{ viewModel.cardListType|json_encode() }}
Returns this to me
{"0":{"label":"Unordered","value":"unordered","selected":true}}
I want to check if the value of viewModel.cardListType is unordered and that it's selected.
I have tried
{% if viewModel.cardListType.value is unordered %}
<p>UNORDERED</p>
{% endif %}
and
{% if viewModel.cardListType.value:unordered %}
<p>UNORDERED</p>
{% endif %}
and several other variations of this.
I don't understand the documentation/ syntax for dropdowns in craft or twig.
Can someone please explain like I'm 5 how this works and how to check the value?
I am using Craft 3 if this changes the syntax
Thanks in advance

"Illegal offset type in isset or empty" when using a Twig macro

Using Grav v1.3.8 (running on PHP 5.6.30), I'm currently getting a Server error ("Illegal offset type in isset or empty") when trying to render a Twig template that is using a macro.
What's interesting is that this only happens when I use the macro by itself. As soon as I append a filter, like trim, everything works as expected.
The (shortened) macro file, helpers.twig:
{% macro ascii(str) %}
{% spaceless %}
{{ str|replace({
'Á': 'A',
'À': 'A',
'Â': 'A',
'Ã': 'A',
....
'ƒ': 'f'
})
}}
{% endspaceless %}
{% endmacro ascii %}
The template (MCVE):
{% import 'macros/helpers.twig' as helpers %}
{% set img = helpers.ascii('günter-berger.jpg') %}
{% if page.media[img] is defined %}
<img src="{{ page.media[img].url }}">
{% endif %}
This will produce the error. I narrowed it down to the if line. Apparently, the macro is working fine, but the condition will throw an error if fed the output of it, unfiltered. Adding any filter, like trim or lower, will get it to work again.
In other words, these work:
{% if page.media['günter-berger.jpg'] is defined %}
{% if page.media[helpers.ascii('günter-berger.jpg')|trim] is defined %}
But this will throw an error:
{% if page.media[helpers.ascii('günter-berger.jpg')] is defined %}
However, trying the same thing on twigfiddle, all three seem to work there.
Maybe an issue with Grav? Can someone point out any possible causes?
I forgot this, but a macro does not return a string but instead returns an instance of a Twig_Markup
{% set test = macro.ascii('Ghünter.jpg') %}
{{ dump(test) }}
Output : object(Twig_Markup)#10679 (2) { ["content":protected]=> string(11) "Ghunter.jpg" ["charset":protected]=> string(5) "UTF-8" }
Because the return type is an object you get this notification as you can't use objects as index. By using a filter on this instance, the magic method __toString method will be called, causing it to return a string, thus making it useable as index for an array
The only was to bypass this, would be writing a filter instead of a macro

how to use split twig template field content type in drupal 8?

I need your help to solve the problem with split in twig.
I want to separate my var {{label}} in an array,
try using
{% set array = label | split (" ")%}
returns empty
I want to separate a field node in an array,
try using
{% set array = content.field_fieldname | split (" ")%}
returns empty
if someone helps me identify what I'm doing wrong, or I indicates a guide and / or tutorial that can solve my problem. Thanks
How do you check that the array is empty?
{% set label = 'this is a label'%}
{% set array = label | split (" ")%}
{% for elem in array %}
{{loop.index}} - {{ elem}}
{% endfor %}
Check this code online here
{{ label }} is in the template as an object, I solved get the string
{% set title = items[0]['content']['#context']["value"]|split(' ', 2) %}
<h1>{{ title[0] }}</h1>
{{ title[1] }}

Resources