NAME

Template::Liquid::Tag::For - Simple loop construct

Synopsis

{% for x in (1..10) %}
    x = {{ x }}
{% endfor %}

Description

For loops... uh, loop over collections.

Loop-scope Variables

During every for loop, the following helper variables are available for extra styling needs:

  • forloop.length

    length of the entire for loop

  • forloop.index

    index of the current iteration

  • forloop.index0

    index of the current iteration (zero based)

  • forloop.rindex

    how many items are still left?

  • forloop.rindex0

    how many items are still left? (zero based)

  • forloop.first

    is this the first iteration?

  • forloop.last

    is this the last iteration?

  • forloop.type

    are we looping through an ARRAY or a HASH?

Attributes

There are several attributes you can use to influence which items you receive in your loop:

limit:int

lets you restrict how many items you get.

offset:int

lets you start the collection with the nth item.

# array = [1,2,3,4,5,6]
{% for item in array limit:2 offset:2 %}
    {{ item }}
{% endfor %}
# results in 3,4

Reversing the Loop

You can reverse the direction the loop works with the reversed attribute. To comply with the Ruby lib's functionality, reversed must be the first attribute.

{% for item in collection reversed %} {{item}} {% endfor %}

Sorting

You can sort the variable with the sorted attribute. This is an extension beyond the scope of Liquid's syntax and thus incompatible but it's useful.

{% for item in collection sorted %} {{item}} {% endfor %}

If you are sorting a hash, the values are sorted by keys by default. You may decide to sort by values like so:

{% for item in hash sorted:value %} {{item.value}} {% endfor %}

...or make the default obvious with...

{% for item in hash sorted:key %} {{item.key}} {% endfor %}

Numeric Ranges

Instead of looping over an existing collection, you can define a range of numbers to loop through. The range can be defined by both literal and variable numbers:

# if item.quantity is 4...
{% for i in (1..item.quantity) %}
    {{ i }}
{% endfor %}
# results in 1,2,3,4

Hashes

To deal with the possibility of looping through hash references, I have chosen to extend the Liquid Engine's functionality. When looping through a hash, each item is made a single key/value pair. The item's actual key and value are in the item.key and item.value variables. ...here's an example:

# where var = {A => 1, B => 2, C => 3}
{ {% for x in var %}
    {{ x.key }} => {{ x.value }},
{% endfor %} }
# results in {  A => 1, C => 3, B => 2, }

The forloop.type variable will contain HASH if the looped variable is a hashref. Also note that the keys/value pairs are left unsorted.

else tag

The else tag allows us to do this:

{% for item in collection %}
    Item {{ forloop.index }}: {{ item.name }}
{% else %}
    There is nothing in the collection.
{% endfor %}

The else branch is executed whenever the for branch will never be executed (e.g. collection is blank or not an iterable or out of iteration scope).

TODO

Since this is a customer facing template engine, Liquid should provide some way to limit ranges and/or depth to avoid (functionally) infinite loops with code like...

{% for w in (1..10000000000) %}
    {% for x in (1..10000000000) %}
        {% for y in (1..10000000000) %}
            {% for z in (1..10000000000) %}
                {{ 'own' | replace:'o','p' }}
            {%endfor%}
        {%endfor%}
    {%endfor%}
{%endfor%}

See Also

Liquid for Designers: http://wiki.github.com/tobi/liquid/liquid-for-designers

Template::Liquid's docs on custom filter creation

Template::Liquid::Tag::Break and Template::Liquid::Tag::Continue

Author

Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/

CPAN ID: SANKO

License and Legal

Copyright (C) 2009-2023 by Sanko Robinson <sanko@cpan.org>

This program is free software; you can redistribute it and/or modify it under the terms of The Artistic License 2.0. See the LICENSE file included with this distribution or notes on the Artistic License 2.0 for clarification.

When separated from the distribution, all original POD documentation is covered by the Creative Commons Attribution-Share Alike 3.0 License. See the clarification of the CCA-SA3.0.