Twig get data from array - twig

I recently asked a question about how I could convert the following to Twig
$firstDate = array_pop(array_keys($dates));
After being suggested to use the slice filter, I worked on it for a while and came up with something that appears to do the job
{% set firstDate = (dates|keys)|last %}
Now I have another problem. I essentially have to do the following in Twig
foreach (array_keys($dates[$firstDate]) as $classLetter) {
I have made a horrible effort to do this, but it doesnt seem to like the []
{% for dates[firstDate]|keys in classLetter %}
Is there anyway I can do something like the above PHP code?
Thanks

After spending a while on it, came up with a solution
{% for classLetter in attribute(dates, firstDate)|keys %}

Related

How to run an object's method in twig without rendering what it returns [duplicate]

I have seen the twig documentation about do tag, but I don't understand its use/useful.
The docs says the follow:
The do tag works exactly like the regular variable expression ({{ ...
}}) just that it doesn't print anything:
and show an example:
{% do 1 + 2 %}
What to solve exactly this tag ?
Good question! I found a link on GitHub to when this was proposed which might add some further info:
Sometimes you want to do things, or call some stuff, and ignore the output. For example if you use a |shift filter to remove some data from an array, doing {{ arr|shift }} will output the removed item, which is not always desirable.
Of course it's possible to do {% set null = arr|shift %}, which won't
output anything, but it also looks weird.
The example in the docs is poor as it explains nothing at all, as you pointed out.

Can't iterate the "filter" filter multiple times

I am trying to assign the result of the "filter" filter (available since Twig 2.10) to a variable so that I can use it multiple times:
{% set filtered = collection|filter(element => element.ok) %}
But unfortunately, if I try to iterate over it multiple times (using the "length" filter counts as such), I get the error
Cannot traverse an already closed generator
after the first one. The error is pretty clear that "filter" actually returns an Generator (which I believe can't be iterated multiple times) and not an array or collection.
The problem is that it makes it impossible to write the following code, for example:
{% if filtered|length > 0 %}
<ul>
{% for element in filtered %}
<li>{{ element }}</li>
{% endfor %}
</ul>
{% endif %}
This code would trigger the error mentioned above on the for loop.
Instead of using a variable I could refilter the original collection, but that doesn't seem optimal if it contains a lot of elements.
I also thought about writing my own filter, wrapping the original one, but I'd live better if I didn't have to.
Is there anything better to do? Should this be considered a bug in Twig (in which case I'll open an issue in their repo)?
Note that https://github.com/dpolac/twig-lambda didn't exhibit this strange behavior but is not compatible with Twig 2.10.
Thanks
That was indeed a bug and it is now fixed

what exactly is haswidgets and widgets in bolt (or twig rather )?

I was just going through the Default theme of bolt CMS, and i came actoss the following lines of code:
{% if haswidgets('aside_top') %}
{{ widgets('aside_top') }}
{% else %}
I googled twig haswidgets and also twig widgets , but i could't find anything.
can somebody explain what these two methods are ? and what exactly do they do ?
They are a feature of Bolt. Extensions can push content to specific places in the backend and also to some places in the frontend, as long as the theme supports that. They are called widgets. the haswidgets() and widgets() twig functions are for checking and displaying them.
You can find more info here https://docs.bolt.cm/3.1/templating/widgets and here https://docs.bolt.cm/3.1/extensions/intermediate/widgets

Yii 2 registerJs in twig templates

In the Yii 2.0 guide it says you can register Javascript code in a twig template like this:
{registerJs key='show' position='POS_LOAD'}
$("span.show").replaceWith('<div class="show">');
{/registerJs}
Tried this but it will simply output the whole snippet {registerJs ... as text on the page without adding it to the page's Javascript Code.
Similar commands like registerJsFile or registerCss aren't working either.
Am I missing something? Thanks!
EDIT:
As Mihai P. noted below, {registerJs} is syntax for Smarty templates. So, the question is: is there a similar way to register inline JS in Twig templates? The documentation only mentions registering assets.
You can use this in your Twig template, which is the current view, to call registerJs.
{% set script %}
var app = new Vue({
el: '#vue-widget',
data: {
message: 'Hello Vue!'
}
})
{% endset %}
{{ this.registerJs(script,4,'vue-widget') }}
The question is 3 years old, I put it here for someone runs into a similar problem.
You can use this in the Twig template with View constant like below:
{{ this.registerJs('$("span.show").replaceWith(\'<div class="show">\');', constant('\\yii\\web\\View::POS_HEAD')) }}
And, you can also call registerJs inside the Yii2 controller, which I think it makes the code cleaner
$this->getView()->registerJs('$("span.show").replaceWith(\'<div class="show">\');', \yii\web\View::POS_HEAD);
Your example is copied from the smarty section not the twig. There are some examples in the twig section that you might want to try.

Twig - Do not interpret

I'm looking for a tag which would enable me to stop interpreting in a section, in a template.
So I'm looking for something that is similar to smarty's literal tag.
Thanks
I think you're looking for {% verbatim %} / {% endverbatim %}. In earlier versions these were called {% raw %} / {% endraw %}.
See also Twig Escaping.
In Twig, it is now verbatim, see http://twig.sensiolabs.org/doc/tags/verbatim.html

Resources