Accessing associative array in twig - twig

I have this array:
$modules = array(
'users',
'submodule' => array(
'submodule1',
'submodule2',
),
);
My question is how can I access all the values and display it on html?
I have tried the following but no luck :
{% for key, module in modules %}
{% if modules.key is iterable %}
{{ module }}
{$ else %}
{{ module }}
{% endif %}
{% endfor %}
Thanks!

If your array has only 2 levels, you can just do something close to what you did:
{% for module in modules %}
{% if module is iterable %}
{% for submodule in module %}
<p>{{ submodule }}</p>
{% endfor %}
{% else %}
<p>{{ module }}</p>
{% endif %}
{% endfor %}
Will give you (with the context you given):
<p>users</p>
<p>submodule1</p>
<p>submodule2</p>
See fiddle
But if your array has an arbitrary number of levels, you should do some recursive using macros:
{% macro show_array(array) %}
{% from _self import show_array %}
{% for module in array %}
{% if module is iterable %}
{{ show_array(module) }}
{% else %}
<p>{{ module }}</p>
{% endif %}
{% endfor %}
{% endmacro %}
{% from _self import show_array %}
{{ show_array(modules) }}
With the following context (in YAML format):
modules:
0: users
submodule:
0: submodule1
1: submodule2
subsubmodule:
0: subsubmodule1
1: subsubmodule2
This will give you:
<p>users</p>
<p>submodule1</p>
<p>submodule2</p>
<p>subsubmodule1</p>
<p>subsubmodule2</p>
See fiddle

Related

How to break “for loop” in Django template

My code is:
{% for key, value in section.items %}
{% for key_t, value_t in title.items %}
{% if value_t.section_id == key|add:"0" %}
<li class="nav-item-header"><div class="text-uppercase font-size-xs line-height-xs">
{{value.title}}</div> <i class="icon-menu" title="Tables"></i></li>
{% endif %}
{% endfor %}
{% endfor %}
I want to break the for loop when if the condition is true. like as
{% for key, value in section.items %}
{% for key_t, value_t in title.items %}
{% if value_t.section_id == key|add:"0" %}
<li class="nav-item-header"><div class="text-uppercase font-size-xs line-height-xs">
{{value.title}}</div> <i class="icon-menu" title="Tables"></i></li>
{{break}}
{% endif %}
{% endfor %}
{% endfor %}
How is it possible? please help me...
There is no way to break out of a for loop in Django Template. However, you can achieve this by setting a variable and adding an if statement on the top like this.
{% set isBreak = False %}
{% for number in numbers %}
{% if 99 == number %}
{% set isBreak = true %}
{% endif %}
{% if isBreak %}
{# this is a comment. Do nothing. #}
{% else %}
<div>{{number}}</div>
{% endif %}
{% endfor %}
for some additional help check out this link
https://dev.to/anuragrana/for-loops-in-django-2jdi
or check this answer on stack overflow
How to break "for loop" in Django template

Loop nested array in twig

Im trying to loop through this (for me) quite complex array with Twig. I want to be able to print out all elements. How would you do that? Below is the array and the code im currently trying.
This is the array: https://pastebin.com/TZSANFpW
I have tried this so far but it gives me error: "Notice: Array to string conversion in "
{% for route in routes %}
<p>
{{ route.admin }}
</p>
{% endfor %}
In order to read out a full array, you would to create some form of recursion.
You could achieve this with a macro in the line of
macros.twig
{% macro readArray(array) %}
{% import _self as macros %}
{% if not array is iterable %}
{{ array }}
{% else %}
{% for k,v in array %}
<ul>
<li>
{{ k }}: {{ macros.readArray(v) }}
</li>
</ul>
{% endfor %}
{% endif %}
{% endmacro %}
main.twig
{% import "macros.twig" as macros %}
{{ macros.readArray(results) }}
example

Passing Twig variables from array into an include

I have an array I'm iterating over to pull in different types of components into my page:
array(
'content'=> array(
'componentA'=>array(
'val'=>'1',
'title'=>'sample title'
),
'componentB'
)
)
I'm attempting to pass variables through from the array to the included template, but I'm not sure how to turn that string produced by the join into something that the include can understand as an array of variables. When I exclude the "with" from the first #components include, it prints out all the default values I've set in the iterable components like I would expect, but still gives me a white screen when I keep the with attribute in. When I display var itself, it returns this string:
(Note, I've also tried putting quotes around the {{k}} to no avail)
{ val:'1',title:'sample title' }
How can I pass the variables from my array to my component?
{% for key,item in content %}
{% if item is iterable %}
{% set var = [] %}
{% for k,v in item %}
{% set temp %}{% if loop.first %} { {% endif %}{{ k }}:'{{ v }}'{% if loop.last %} } {% endif %}{% endset %}
{% set var = var|merge([ temp ]) %}
{% endfor %}
{% set var = var|join(',') %}
{{ include ("#components/" ~ key ~ ".tmpl",var) }}
{% else %}
{{ include ("#components/" ~ item ~ ".tmpl") }}
{% endif %}
{% endfor %}
Your include statements are incorrect. You are using {{ include ... }}, which should be {% include ... %}.
The following snippet should work, if you only want to provide the data from the array (and not the loop data):
{% for key,item in content %}
{% if item is iterable %}
{% include ("#components/" ~ key ~ ".tmpl") with item %}
{% else %}
{% include ("#components/" ~ item ~ ".tmpl") %}
{% endif %}
{% endfor %}
You can then use {{ val }} and {{ title }} within your component template.
If you want to include the loop data, you can use:
{% for key,item in content %}
{% if item is iterable %}
{% include ("#components/" ~ key ~ ".tmpl") with {item: item, loop: loop} %}
{% else %}
{% include ("#components/" ~ item ~ ".tmpl") %}
{% endif %}
{% endfor %}
You can then use {{ item.val }}, {{ item.title }} and {{ loop.index }} in your component template.

Navigation link works on mobile but not on desktop

i have this website http://sds-test.nowcommu.myhostpoint.ch/de (please use the "de" at the end) and the last link of the navigation "RECHENZENTRUM" does not works on desktop but works on mobile. How can i solve it? This is the twig code:
{% extends 'partials/base.html.twig' %}
{% set show_onpage_menu = header.onpage_menu == true or header.onpage_menu is null %}
{% macro pageLinkName(text) %}{{ text|lower|replace({' ':'_'}) }}{% endmacro %}
{% block javascripts %}
{% if show_onpage_menu %}
{% do assets.add('theme://js/singlePageNav.min.js') %}
{% endif %}
{{ parent() }}
{% endblock %}
{% block bottom %}
{{ parent() }}
{% if show_onpage_menu %}
<script>
// singlePageNav initialization & configuration
$('#navbar').singlePageNav({
offset: $('#header').outerHeight(),
filter: ':not(.external)',
updateHash: true,
currentClass: 'active'
});
</script>
{% endif %}
{% endblock %}
{% block header_navigation %}
{% if show_onpage_menu %}
<ul class="navigation">
{% for module in page.collection() %}
{% set current_module = (module.active or module.activeChild) ? 'active' : '' %}
<li class="{{ current_module }}">{{ module.menu }}</li>
{% endfor %}
{% set datacenter_page = page.find('/services/datacenter') %}
<li>{{ datacenter_page.menu() }}</li>
</ul>
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
{% block content %}
{{ page.content }}
{% for module in page.collection() %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
The 'rechenzentrum' link is rendered correctly, and copying the link location via right click gives a correct URL that opens a seemingly correct page. So the template rendering is fine.
The link has two onclick handlers attached to it, though. Probably one of them fails and thus prevents navigation. (The JS is minified so I did not try to debug it.)

Is it possible to turn on spaceless mode only in certain situations in twig?

I want to do something like this:
{% if compress %}{% spaceless %}{% endif %}
...
{% if compress %}{% endspaceless %}{% endif %}
I'm trying to pass ['compress' => true] to the template from PHP to turn on spaceless mode. But it causes an error; template tags need to be nested properly.
Is there any technique that would let me turn spaceless on/off from PHP?
You would have to restructure your template to do something like this instead.
{% import _self as example %}
{% macro stuff(obj) %}
output stuff with {{ obj.name }}, etc...
{% endmacro %}
{% if compress %}
{% spaceless %}
{{ example.stuff(bla) }}
{% endspaceless %}
{% else %}
{{ example.stuff(bla) }}
{% endif %}
Using macros avoids you have to duplicate the content. The import statement at the top is important, so don't forget it.
page.twig:
{% block page %}
page content
{% endblock %}
index.twig:
{% extends 'page.twig' %}
{% block page %}
{% if compress %}
{% spaceless %}
{{ parent() }}
{% endspaceless %}
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}

Resources