Hash with numbers as keys - twig

I'm trying to create a hash of month days (1..31) in twig:
{% set days = {} %}
{% for i in 1..31 %}
{% set days = days|merge({(i) : i}) %}
{% endfor %}
So I expect to have something like:
1 -> 1
2 -> 2
...
31 -> 31
Instead it creates a hash started from 0:
{% for key, option in days %}
{{ key }} -> {{option }}
<br />
{% endfor %}
0 -> 1
1 -> 2
...
30 -> 31
I'm pretty sure that there is more elegant way to create a hash I want. Also will appreciate some explanation of unexpected output. Thanks

Use loop.index. For example,
{% for option in days %}
{{ loop.index }} - {{ option }}
<br />
{% endfor %}

Related

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 3: Break in a loop

Does anyone know how to loop through an array and find the first of an item then break the loop in twig?
Like this
Loop->find 3
- 2
- 2
- 3 - then break loop here
- 1
- 3
Try this code. It's working on the twig <= 2 version.
{% set break = false %}
{% set numbers = [2,2,3,1,3] %}
{% for number in numbers if not break %}
- {{ number }} <br/>
{% if number == 3 %}
{% set break = true %}
{% endif %}
{% endfor %}
But in Twig 3, it's not working. You can try the below code it's working for twig 3.
{% set break = false %}
{% set numbers = [2,2,3,1,3] %}
{% for number in numbers %}
{% if break == false %}
- {{ number }} <br/>
{% if number == 3 %}
{% set break = true %}
{% endif %}
{% endif %}
{% endfor %}
I have read the twig 3 document but I can't fine break/continue concept on that.
=> Output
- 2
- 2
- 3

Increase loop index in twig

Below is my code. I want to increase J loop index in between inner loop so I have incremented J variable but it is not working.
`{% for j in 0..(products|length-1) %}
{% for f in 0..(rows-1) %}
{% set j = j + 1 %}
{% endfor %}
{% endfor %}`
Is there any other way to increase loop index?
Its not possible to alter the loop indeces of twig due to the fact of how the loops are compiled
{% for i in 1..5 %} for example gets compiled as
$context['_seq'] = twig_ensure_traversable(range(1, 5));
foreach ($context['_seq'] as $context["_key"] => $context["i"]) {
//..
}
I do have another aproach for you to solve this with twig
{% set rows = 2 %}
{% set items = ((products|length) / rows) | round %}
{% for product in products %}
{% if loop.index0 % items == 0 %}
<div class="row">
{% endif %}
<div class="product">
{{ product }}
</div>
{% if loop.index % items == 0 or loop.last %}
</div>
{% endif %}
{% endfor %}

Access posts from other page in jekyll pagination

Jekyll pagination enables you to arrange posts neatly on pages. I would like to put the range of dates as a tooltip on the links to the pages, just as:
<li class="pager-item">
Page 2
</li>
The obvious way to do so would be to take the date of the first and the last post on a page. Unfortunatly jekyll-pagination only seems to deliver a list of posts for the current page via paginator.posts.
Maybe I just can't find it in the documentation, so I ask you: is it possible to access a list of posts from another page in jekyll pagination? Something like paginator.pages.2.posts?
An alternate approach would be to build my own paginaton, which should be no problem, but I would prefer to use built-in functions.
You can get the information indirectly:
paginator.previous_page and paginator.next_page give you the page number of respectively the previous and the next pagination page, or nil if the page does not exists.
paginator.per_page gives you the number of posts per page.
paginator.total_posts gives you the total number of posts in the site.
site.posts gives you a reverse chronological list of all posts.
So given the current paginator object, ensuring paginator.next_page != nil, you know the posts from the next pagination page are indexed in site.posts from a to b (included) with:
a = (paginator.next_page) * paginator.per_page
b = a + paginator.per_page - 1
Last pagination page may not be complete: remember checking b < paginator.total_posts.
Ensuring paginator.previous_page != nil, same goes for previous pagination page with:
a = (paginator.previous_page) * paginator.per_page
b = a + paginator.per_page - 1
My current approach looks like this:
{% if include.page > 0 and include.page <= paginator.total_pages %}
{% assign first = include.page | minus:1 | times:paginator.per_page %}
{% assign last = paginator.per_page | times:include.page | minus:1 %}
{% if last > paginator.total_posts %}
{% assign last = paginator.total_posts | minus:1 %}
{% endif %}
{{ site.posts[first].date | date: "%d.%m.%Y" }} bis {{ site.posts[last].date | date: "%d.%m.%Y" }}
{% else %}
OUT_OF_RANGE
{% endif %}
I really don't like the Liquid-Syntax :D
Or :
{% comment %} NOTE : shortcut "p" for "paginator" {% endcomment %}
{% assign p = paginator %}
{% comment %} date formating (see shorthand formats in Ruby's documentation : http://ruby-doc.org/core-2.3.3/Time.html#method-i-strftime) {% endcomment %}
{% assign dateFormat = "%y %b %d" %}
<ul>
{% for post in p.posts %}<li>{{ post.title }} - {{ post.date | date: dateFormat }}</li>
{% endfor %}
</ul>
{% comment %}++++++++++ if previous page == newest posts {% endcomment %}
{% if paginator.previous_page %}
{% assign prevPage = p.page | minus: 1 %}
{% assign prevPageLastIndex = prevPage | times: p.per_page | minus: 1 %}
{% assign prevPageFirstIndex = prevPageLastIndex | minus: p.per_page | plus: 1 %}
{% assign prevPagefirstPostDate = site.posts[prevPageFirstIndex].date | date: dateFormat %}
{% assign prevPagenextPageLastPostDate = site.posts[prevPageLastIndex].date | date: dateFormat %}
{% capture prevPageLink %}
<p><a href="{{ paginator.previous_page_path }}"></p>
Newest posts from
{% if prevPagefirstPostDate != prevPagenextPageLastPostDate %}
{{ prevPagenextPageLastPostDate }} to {{ prevPagefirstPostDate }}
{% else %}
{{ prevPagenextPageLastPostDate }}
{% endif %}
</a>
{% endcapture %}
{% endif %}
{% comment %} ++++++++++ if next page = oldest posts {% endcomment %}
{% if paginator.next_page %}
{% assign nextPage = p.page | plus: 1 %}
{% assign nextPageFirstIndex = p.page | times: p.per_page %}
{% comment %}>>Next page is not the last page = normal computing {% endcomment %}
{% if nextPage != p.total_pages %}
{% assign nextPageLastIndex = nextPageFirstIndex | plus: p.per_page | minus: 1 %}
{% comment %}>>Next page is the last page compute index from p.total_posts{% endcomment %}
{% else %}
{% assign nextPageLastIndex = p.total_posts | minus: 1 %}
{% endif %}
{% assign nextPagefirstPostDate = site.posts[nextPageFirstIndex].date | date: dateFormat %}
{% assign nextPageLastPostDate = site.posts[nextPageLastIndex].date | date: dateFormat %}
{% capture nextPageLink %}
<p><a href="{{ paginator.next_page_path }}"></p>
Previous posts from
{% if nextPagefirstPostDate != nextPageLastPostDate %}
{{ nextPageLastPostDate }} to {{ nextPagefirstPostDate }}
{% else %}
{{ nextPageLastPostDate }}
{% endif %}
</a>
{% endcapture %}
{% endif %}
{{ prevPageLink }}
{{ nextPageLink }}

how to subtract dates in twig?

{%for mat in setQuery %}
{% set datePost = mat.data_criacao|date('d-m-Y') %}
{% set today = "now"|date('d-m-Y') %}
{{today- datePost}}
{% endfor %}
datePost = 17-04-2015
today = 06-05-2015
the example above returns it: -11
The issue was resolved with the following code:
{% set datePost = mat.data_criacao|date('d-m-Y') %}
{% set today = "now"|date('d-m-Y') %}
{% set difference = date(today).diff(date(datePost))%}
{% set leftDays = difference.days %}
{% if datePost == today %}
1 day
{% else %}
{{ leftDays }}
{% endif %}
You must write your custom twig extension:
You must write a twig function as described here with the following code for make diff via php function:
$calcFrom = $from;
$calcTo = $to;
$now->diff($calcFrom)->format("%a")
And make it available via a Twig extension.
If you are using symfony2 framework You can use the KnpTimeBundle
In the Twig:
This compare with the current date:
{# Returns something like "3 minutes ago" #}
{{ time_diff(form) }}
This compare with the another date:
{# Returns something like "3 minutes ago" #}
{{ time_diff(form , to ) }}
Hope this help

Resources