Reputation: 4902
How can I loop by index?
Foo.java
public Foo {
private List<String> tasks;
...
}
index.html
<p>Tasks:
<span th:each="${index: #numbers.sequence(0, ${foo.tasks.length})}">
<span th:text="${foo.tasks[index]}"></span>
</span>
</p>
I got parse error
org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as each: "${index: #numbers.sequence(0, ${student.tasks.length})}"
Upvotes: 57
Views: 128788
Reputation:
First of all, please excuse my poor English.
Please be aware that, in my experience, the status variable ([1]), regarding index
and count
values, DOES not keep track of the status of the iteration, but returns the position of the current object in the list you're looping for.
For example.
You have a list called pairs
of 6 pairs like this
0: [id=10, fk=2]
1: [id=20, fk=2]
2: [id=30, fk=2]
3: [id=40, fk=1]
4: [id=50, fk=1]
5: [id=60, fk=1]
and you want to print those who have fk=1
BEFORE those who have fk=2
(it's an example, sorting is not important, here).
So, if you use a th_each="p:${pairs}"
followed by a th:if="p.id == 1"
, you'll obtain
[id=40, fk=1]
[id=50, fk=1]
[id=60, fk=1]
(...)
as expected.
But, what are you expecting from pStat.index
and pStat.count
values?
I guess
(0,1)
(1,2)
(2,3)
but (please verify using a <pre>([[${pStat.index}]], [[${pStat.count}]])</pre>
), you'll obtain
(3,4)
(4,5)
(5,6)
that is to say, the position of these pairs in the list, not the status of the iteraction itself.
This could be fine for you, but be aware that, for example, if you try to keep a count on how much times you looped extracting data from a list o hundred objects (for example to insert a <br />
every ten values) results can surprise you, if the sequence of the list is not the sequence in which you'll use it.
If this is your case, a way to obtain this is extracting sublist using Collection Selection ([2]) in conjunction with Thymeleaf's #lists.toList()
as in
<th:block th:with="sublist=${#pairs.toList(list.?[fk ==1])}">
.
This way you'll obtain
0: [id=40, fk=1]
1: [id=50, fk=1]
2: [id=60, fk=1]
and your first pair will have index 0
and count 1
.
Maybe this is a bug of the current verison of thymeleaf I'm using, or is not so clearly stated in documentation, but this is what I discovered staring at few code lines unexpectedly behaving (and some debugging).
Thymeleaf Iterations [1]: https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#keeping-iteration-status
SpEL Collection Selection [2]: https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/collection-selection.html
Upvotes: 0
Reputation: 37916
Thymeleaf always declares implicit iteration status variable if we omit it.
<span th:each="task : ${foo.tasks}">
<span th:text="${taskStat.index} + ': ' + ${task.name}"></span>
</span>
Here, the status variable name is taskStat
which is the aggregation of variable task
and the suffix Stat
.
Then in the loop, we can refer to taskStat.index
, taskStat.size
, taskStat.count
, taskStat.even
and taskStat.odd
, taskStat.first
and taskStat.last
.
Source: Tutorial: Using Thymeleaf - 6.2 Keeping iteration status
Upvotes: 52
Reputation: 86774
Thymeleaf th:each
allows you to declare an iteration status variable
<span th:each="task,iter : ${foo.tasks}">
Then in the loop you can refer to iter.index
and iter.size
.
See Tutorial: Using Thymeleaf - 6.2 Keeping iteration status.
Upvotes: 136