I am developing a simple application using Spring + Thymeleaf. On one of the pages I have a list of items which needs to be paginated.
Ideally I would like to only send the currPageNo
(the number of the current page) and numOfPages
(the total number of pages) variables to the view and the rest of the work would be done in there (this is a presentation issue and has nothing to do with the business logic). If, however, the cleanest solution would require me to do some computation in the controller first, I would accept it as a small evil.
I would like to get the list of pages in the following form.
<Prev | 1 | ... | 3 | 4 | 5 | 6 | 7 | ... | 15 | Next>
I was only able to come with the following solution. It works but I believe that you will agree that it is very messy and really hard to read.
Moreover, in addition to currPageNo
and numOfPages
I had to send two more variables to the view. The ideal solution would not require me to do that.
firstPageNo = Math.max(2, currPageNo - 2)
lastPageNo = Math.min(numOfPages - 1, currPageNo + 2)
The current version of my code follows.
<ul>
<li th:if="${currPageNo > 1}">
<a th:href="@{/items.html(pageNo = ${currPageNo - 1})}" href="">< Prev</a>
</li>
<li th:class="${currPageNo == 1} ? 'selected'">
<a th:href="@{/items.html(pageNo = 1)}" th:if="${currPageNo > 1}" href="">1</a>
<span th:if="${currPageNo == 1}">1</span>
</li>
<li th:if="${currPageNo >= 5}">
...
</li>
<li th:each="pageNo : ${#numbers.sequence(firstPageNo, lastPageNo)}" th:class="${currPageNo == pageNo} ? 'selected'">
<a th:href="@{/items.html(pageNo = ${pageNo})}" th:if="${pageNo != currPageNo}" th:text="${pageNo}" href="">2</a>
<span th:if="${pageNo == currPageNo}" th:text="${pageNo}">2</span>
</li>
<li th:if="${currPageNo <= (numOfPages - 4)}">
...
</li>
<li th:class="${currPageNo == numOfPages} ? 'selected'">
<a th:href="@{/items.html(pageNo = ${numOfPages})}" th:if="${currPageNo < numOfPages}" th:text="${numOfPages}" href="">10</a>
<span th:if="${currPageNo == numOfPages}" th:text="${numOfPages}">1</span>
</li>
<li th:if="${currPageNo < numOfPages}">
<a th:href="@{/items.html(pageNo = ${currPageNo + 1})}" href=""> Next ></a>
</li>
</ul>
The following list sumarizes the issues that I would like to get rid of the most. I understand that some of them are inherent to the platform but still, the list seems to be quit long and the code messy.
- Having to send the precomputed values of
firstPageNo
andlastPageNo
to the view from the controller. - Having to use
<
instead of<
in the expressions. - Having to use both an anchor and a span with mutually exclusive conditions in order for the browser not to use a link for the current page.
I also welcome any other suggestions about how to improve the quality of the code.
I understand that perhaps this question would be a better fit for the Code Review site, but, as Thymeleaf seems to be a technology with a tiny user base yet, I expect a reasonable answer rather here on Stack Overflow, which has a much greater user base (I believe).
If, however, such a question is really not welcome here, please consider moving it to the right site instead of closing it so that I get the advice I need.
Similar to solution described in http://www.javacodegeeks.com/2013/03/implement-bootstrap-pagination-with-spring-data-and-thymeleaf.html
but without using wrapper around Spring Pageable
Another option would be Ben Thurley's solution. We have implemented it and it's working smoothly: http://bthurley.wordpress.com/2012/07/18/spring-mvc-with-restful-datatables/
It lacks couples of items, like the filter argument for the search, but you can easily add via the PagingCriteria object and make sure to add it on the TableParamArgumentResolver.
I have this almost ready, hope it helps....