I'm trying to print out a table with keys and values from a 2d-array in twig. The only issue is, that I'm trying to get the values and keys dynamically printed depending on the twig result I get back.
The array I'm getting back from another function can be different with every call, so my goal would be to write a function once instead of multiple times depending on the typ of data I recive.
The array I get is in {{ tableContent }}.
One example of the values are:
{
["Type"] => string(4) "2021"
["Description"] => string(11) "Stundenlohn"
["Symbol"] => string(3) "ABC"
}, {
["Type"] => string(4) "2024"
["Description"] => string(9) "Something"
["Symbol"] => string(3) "XYZ"
}
so in this case I want the table to look something like:
# | Type | Description | Symbol
--+------+-------------+--------
0 | 2021 | Stundenlohn | ABC
1 | 2024 | Something | XYZ
this would work quite well, if I always know the names of the array keys:
{% for key, u in tableContent %}
<li>{{ key }}: {{ u.Type }}</li>
{% endfor %}
And with this I'd get 0: 2021 and 1: 2024
is there a way to not use (in my case) Type but somehow the index?
With this solution I'm working on at the moment I only get the first value:
{% for array in tableContent %}
{% for id, key in array %}
{{id }} | {{key}}<br/>
{% endfor %}<br/>
{% endfor %}
Related
I'm having some problems using twig.
When I try to bring an array to javascript, the array always returns the maximum length of 100.
i.e.
{% set getnumbers%}
{% for number in numberLists %}
{{number['odd'] | json_encode() }},
{% endfor%}
{% endset%}
var getNumbers = [
1,
3,
5 ...
197,
199
];
console.log (getNumbers);
On the console:
(100) [
1,
3,
5 ...
197,
199]
length: 100
Also
{{ numberLists | length }} returns = [100];
Although the length returns as 100, it is 100 numbers per page. the last number of the array should be 503.
I believe that the array is limited in some way due to the pagination that is set for every 100 elements.
this is the code for the pagination that is by default in the template
{% if pagination['count'] > 100 %}
{% if searchList %}
{% set params = {} %}
{% for search in searchList %}
{% set params = params | merge([search['name'] ~ '=' ~ search['value']]) %}
{% endfor %}
{% set params = '?' ~ params|join('&') %}
{% endif %}
I'm using a third-party system with an integrated API.
Unfortunately I don't have access to the back-end to be making any adjustments there, the only part I have access to, are the templates to configure some java, html and use some variables and arrays informed by the developer.
in the documentation provided by the developer, there is nothing relevant about this.
The dump function is appearing as unrecognized, from what I searched, it is not enabled by default, so it must be disabled.
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
Let's assume I have an array $cars where $cars = [$toyota, $vw] and
$toyota= [
'id' => 1,
'color' => 'green',
];
$vw= [
'id' => 7,
'color' => 'red',
];
I wanna do a check in twig to see if at least one of the cars ID exists in a dedicated array ([3, ,7, 15]).
What's the best way to do this? Doing a for loop is not ideal since I cannot do a break if I found the first element matching my criteria. And I also don't wanna print a text twice if both elements satisfy the condition. I just want to print a text if one element does.
I tried doing something weird like
{% if cars in [3, 7, 15] %} .... {% endif %} but if obvously doesn't work since I need to check the id of a car, not the object...
Any suggestions on how to best solve this is much appreciated.
P.S. I know using array_filter in the controller makes it much easier, but sadly that doesn't work for me. That's because I use AJAX and after a submit, I won't have access to cars anymore. Therefore, I need to do it in the view..
You can do something like this (see https://twigfiddle.com/8u3eh5):
{% set found = false %}
{% for car in cars %}
{% if car.id in ids %}
{% set found = true %}
{% endif %}
{% endfor %}
{% if found %}
found
{% else %}
not found
{% endif %}
However, even if this is a working solution, you will be better off by implementing this in PHP code and expose such a function as a Twig test.
Just add a new filter to twig
$twig = new Twig_Environment($loader);
$twig->addFilter(new Twig_SimpleFilter('has', function($haystack, $needles) {
if (!is_array($needles)) $needles = [ $needles, ];
return count(array_intersect($haystack, $needles)) > 0;
});
Which you then can use like the following inside twig
{% set data = [ 'foo', 'bar', 'foobar', 'lorem', 'lipsum' ] %}
{% if data | has('foo') %}
data contains foo
{% endif %}
{% if data | has(['lorem', 'lipsum', 'boat']) %}
data contains lorem, lipsum or boat
{% endif %}
I'm using node.js and MongoDB to create an app. I have 2 collections and you could say that they are in a 1:N relation.
col1 = { id="abc", name="London", createdAt=... }
col2 = { id="..." link="abc", temperature=31.24, sentAt=... }
I would like to create a table that would display it's name and temperature (the latest one, because there could be more)
Name | Temperature
London | 31.24
So I'm passing both objects from MongoDB into nunjucks where I'm trying to cycle through them like so:
{% for city in col1 %}
{% for data in col2 %}
{{ city.name }} | {{ data.temperature }}
{% endfor %}
{% endfor %}
But if I do this the result is this:
Name | Temperature
London | 31.24
London | 31.24
And I know why that is but I don't really know how to fix it and I think that it has to have some common way to fix this.
{% set data = {} %}
{% for city in col1 %}
{% for data in col2 %}
{% set data[city.name] = data.temperature %}
{% endfor %}
{% endfor %}
{% for city, temperature in data %}
{{city}} | {{temperature}}
{% endfor %}
But the best way is uniqued values outside of nunjucks template.
I have a multi dimensional array along the lines of
array(2) {
[11]=> array(1) {
["L2J"]=> array(1) {
["VS7"]=> array(2) {
["26 Feb 2015 12:00"]=> array(2) {
["C"]=> string(1) "9"
["D"]=> string(1) "9"
}
["26 Feb 2015 13:00"]=> array(2) {
["C"]=> string(1) "9"
["D"]=> string(1) "6"
}
}
}
}
}
Now I have done some looping and I am now at the point where I have access to the dates.
{% for sid, psuedos in alerts %}
{% for psuedo, flights in psuedos %}
{% for flight, dates in flights %}
{% endfor %}
{% endfor %}
{% endfor %}
Now I am converting some normal PHP code and at this point, I would do
$firstDate = array_pop(array_keys($dates));
Is there any way to do something like this in Twig? I have searched about but cant seem to find anything.
Update
This is my latest effort, can't seem to get it to slice the last array element though
{% set firstDate = [dates|keys]|last|slice(1) %}
There isn't a Twig function that will do exactly what array_pop() does (return the last array element and shorten the array at the same time), but there are ways to do them separately.
Given:
{% set array = [1,2,3,4,5] %}
To get the last element, use Twig's last filter.
{{ array|last }}
{# returns '5' #}
You can remove only the last element with the slice filter like this: slice(0,-1)
{% set array = array|slice(0,-1) %}
{# array = [1,2,3,4] #}
... or the Craft without filter:
{% set arrayLast = array|last %}
{% set array = array|without(arrayLast) %}
{# array = [1,2,3,4] #}
pop last element
{% set array = [1,2,3] %}
{% set value = array|last %}
{{ value }} {# return 3 #}
{% set array = array|slice(start, length - 1) %}
{% for value in array %}
{{ value }} {# return 1,2 #}
{% endfor %}
pop the first element
{% set array = [1,2,3] %}
{% set value = array|first %}
{{ value }} {# return 1 #}
{% set array = array|slice(start + 1, length) %}
{% for value in array %}
{{ value }} {# return 2,3 #}
{% endfor %}
Just as a quick check, have you tried slice(-1)?
Passing a negative number as the first parameter should start at the end of the array and work that many back.