I have created a simple Jekyll page (processed and hosted by GitHub Pages) with a Liquid counter variable where I loop through some data and dump it out and count the number of items with a given property.
For example:
Complete Before: {{ complete }}
{% for book in books %}
Title: {{book.Title}}
{% if book.Completed == "true" %}
{% increment completed %}
{% endif %}
{% endfor %}
Complete After: {{ complete }}
Now I have the same chunk of code on two different pages, but the data in books is different it both cases, but the value of the variable completed
looks like it's being saved across the processing of both pages which results in page one looking like
Complete Before:
Title: Foo
Title: Bar
Complete After: 2
and page two looks like
Complete Before: 2
Title: Baz
Complete After: 3
How can I get the completed variable to be unique per page without needing to change each page to use a different variable name.
I recommend to use assign
in this case and increment the variable with the plus
filter. increment
behaves a little different than one expects, it does not modify a common Jekyll variable value:
{% assign complete=0 %}
Complete Before: {{ complete }}
{% for book in books %}
Title: {{book.Title}}
{% if book.Completed == "true" %}
{% complete=complete | plus:'1' %}
{% endif %}
{% endfor %}
Complete After: {{ complete }}
Update
The problem relies in its scope, at least, that is not what I naturally expect, this is a simple example to show it:
{% for post in site.posts limit: 2%}
increment {{forloop.index}}
- before {{complete}}
- current increment: {% increment complete %}
- after {{complete}}
<hr>
{% endfor %}
New loop
{% for post in site.posts limit: 2%}
increment {{forloop.index}}
- before {{complete}}
- current increment: {% increment complete %}
- after {{complete}} EXPECTED: {{forloop.index}}
<hr>
{% endfor %}
Output:
increment 1
before
current increment: 0
after 1
increment 2
before 1
current increment: 1
after 2
New loop
increment 1
before 2
current increment: 2
after 3 EXPECTED: 1
increment 2
before 3
current increment: 3
after 4 EXPECTED: 2
If you look at liquid::increment code, you can see how it works and where is the boundary between context myvar
and local myvar
.
note that context myvar
is passed across all pages, posts. It's a "global" variable.
On first page :
{% increment myvar %}
-> output : 0
- retrieve context
myvar
, assign 0 if it's nil
- store it in a temporary variable
- does a post increment (
myvar++
)
- stores the value (1) in the
myvar
context variable
- print temporary variable (0)
{{ myvar }}
-> output : 1
As myvar
is not assigned to a local variable, this liquid tag is using the fallback value of the context variable myvar
but doesn't modify it.
On second page :
{% assign myvar = 100 %}
assign 100
to local myvar
variable.
{% increment myvar %}
-> output : 1
- retrieve context
myvar
, which is 1
- store it in a temporary variable
- does a post increment (
myvar++
)
- stores the value (2) in the
myvar
context variable
- print temporary variable (1)
{{ myvar }}
-> output : 100
As myvar
is assigned to a local variable, use it.
Conclusion
If you need a local counter use @marcanuy solution.
If you need a global counter use {% increment myvar %}
tag and do not rely on {{ myvar }}
to print its value, because you're not sure that a local myvar
is assigned/declared.