I am studying thymeleaf recently and I need a little help for a college project. Basically I have to apply the iterator pattern design to iterate on a list of objects and then print them on video on my website. I created my own iterator but however when I try to iterate with thymeleaf only the first element of the list is printed, the others are ignored. The code for my iterator is:
public class ConcreteIterator<T> implements MyIterator<T> {
private List<T> list;
private int index;
public ConcreteIterator(List<T> list) {
this.list = list;
this.index = 0;
}
@Override
public boolean hasNext() {
return index < list.size();
}
@Override
public T next() {
if (hasNext()) {
T item = list.get(index);
index++;
return item;
} else {
throw new IndexOutOfBoundsException("No items left!");
}
}
}
Il codice thymeleaf è, invece, il seguente:
<div th:while="${gameIterator.hasNext()}">
<div th:text="${gameIterator.getCurrent().getName()}"></div>
<div th:text="${gameIterator.getCurrent().getDescription()}"></div>
<th:block th:width="${gameIterator.next()}"></th:block>
</div>
I solved it this way and now print the whole list:
<div th:each="i : ${#numbers.sequence(1, size)}">
<div th:text="${gameIterator.getCurrent().getName()}"></div>
<div th:text="${gameIterator.getCurrent().getDescription()}"></div>
<div th:if="${gameIterator.hasNext()}">
<th:block th:width="${gameIterator.next()}"></th:block>
</div>
</div>
However it is a very forced method and I would like, if I could, to do it with just using the while as in the code above (alternatively I could also use javasccript, but I don’t know how to get the iterator in the javascript script to iterate). Thanks to anyone who will help me or give me a tip!
If possible (if you are using Iterable
/Iterator
provided by the JDK and have access to the Iterable
), try using th:each
with the Iterable
instead of directly using the Iterator
:
<div th:each="current:${gameIterable}">
<div th:text="${current.getName()}"></div>
<div th:text="${current.getDescription()}"></div>
</div>
However, if this is not possible, you can use th:with
:
<div th:while="${gameIterator.hasNext()}">
<th:block th:with="current=${gameIterator.next()}">
<div th:text="${current.getName()}"></div>
<div th:text="${current.getDescription()}"></div>
</th:block>
</div>
This assigns the value returned by Iterator#next
to a variable (current
) and then uses that variable as needed.
If you need to iterate over it multiple times, you might want to put the elements in a List
which you can then iterate over multiple times. You can do something like this in your controller:
Iterable<YourClass> gameIterable = whateverGetsYourIterable();
List<YourClass> gameList = new ArrayList<>();
gameIterable.forEach(gameList::add);
model.addAttribute("gameList",gameList)
and then use th:each
in your Thymeleaf code.