fluid
fluid copied to clipboard
forloop.first ambiguity with offset
If offset is defined, what should first represent? The first item of the collection or the first iteration element?
Same with offset: continue.
Hi,
I've found forloop.first and forloop.last to be the first and last iteration of the loop, not the first and last item in the underlying collection. For example:
Template
{% assign array = '1,2,3,4' | split: ',' -%}
{% for item in array limit: 1 -%}
a{{ item }} {{ forloop.first }} {{ forloop.last }}
{% endfor -%}
{% for item in array offset: continue -%}
b{{ item }} {{ forloop.first }} {{ forloop.last }}
{% endfor %}
Expected output
a1 true true
b2 true false
b3 false false
b4 false true
forloop.length behaves similarly.
Template
{% for item in (1..6) limit: 2 -%}
a{{ item }}-{{ forloop.length }},
{%- endfor -%}
{% for item in (1..6) offset: continue -%}
b{{ item }}-{{ forloop.length }},
{%- endfor -%}
Expected output
a1-2,a2-2,b3-4,b4-4,b5-4,b6-4,
You might also be interested in the test cases defined here. All of which pass using Ruby Liquid version 5.1.0.
Kindest regards, James
Thanks @jg-rp for the test cases. Do you know what is the rule to relate loops between each others? For instance what if there is a loop on (1..6) then the next loop is on (5..9), should continue start from the previous index? Or does it have to match the same value to be a continuation?
I believe the name of the loop variable and a string representation of the target collection or range are used to distinguish one loop from another.
Ruby Liquid uses a hyphen to separate the two. So an offset for {% for x in y limit: 2 %} would use the key "x-y", and {% for item in (1..6) limit: 3 %} would be "item-(1..6)".
Note that this approach disregards the contents of the target collection. Consider this template that reassigns foo between loops.
{% assign foo = '1,2,3,4,5,6' | split: ',' -%}
{% for item in foo limit: 3 -%}
{{ item -}}
{% endfor -%}
{% assign foo = 'u,v,w,x,y,z' | split: ',' -%}
{% for item in foo offset: continue -%}
{{ item -}}
{% endfor -%}
Output
123xyz
Awesome. In my current implementation I am only doing it for identifiers, so this is something else to fix. More features than whatever people are using or aware of even of though.
Related, there is a forloop.name property that should contain the token used by the loop.
https://github.com/harttle/liquidjs/commit/6dc7fada72467418806c1ee4bd7eaf3003690fe6
https://github.com/jg-rp/liquid/commit/e4e902429e40b85a0b6401d1637f8c09d615c253