I've been working on a flexible pagination solution for my app, here's the fragment code:
<div th:fragment="pagination(form, postUrl)">
<nav aria-label="Page Navigation">
<ul class="pagination justify-content-center">
<li class="page-item"
th:classappend="${form?.page == 1} ? disabled : ''">
<form th:action="@{${postUrl}}" th:object="${__${form}__}"
method="post">
<input hidden th:field="${form?.page}" th:value="${form?.page} - 1" />
<button class="page-link" th:text="#{page.previous}" />
</form>
</li>
<div
th:with="pageLimit=${form?.totalPages > 0} ? ${form?.totalPages} : 1">
<li class="page-item"
th:each="i : ${#numbers.sequence(1, pageLimit)}">
<form th:action="@{${postUrl}}" th:object="${__${form}__}"
method="post">
<input hidden th:field="*{page}" th:value="${i}" />
<button class="page-link" style="border-radius: 0px"
th:text="${i}" />
</form>
</li>
</div>
<li class="page-item">
<form th:action="@{${postUrl}}" th:object="${__${form}__}"
method="post">
<input hidden th:field="*{page}" th:value="${form?.page} + 1" />
<button class="page-link" th:text="#{page.next}" />
</form>
</li>
</ul>
</nav>
</div>
and the fragment variables are passed in like this:
<div
th:replace="fragments/pagination :: pagination(${objectForm}, '/my/url-is-here')">
However, on processing the view, I get this error (shortened for clarity):
Exception evaluating SpringEL expression: "my.object.ObjectForm@66bc4dd8" (template: "fragments/pagination" - line 6, col 37)
...
org.springframework.expression.spel.SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'bean_ref(@)'
It's most definitely something wrong with the bean preprocessing, because if I use the code as-is without fragments, __${form}__
or th:with
variables, it comes out OK. So does anyone know what's going on here?
Any insight would be appreciated!
So I worked on it some more, and it turns out I misunderstood how the Thymeleaf variables are being used. I believe it had something to do with th:field
; changing it to name
solved the issue.
My understanding is that Thymeleaf variables are variables that have already been processed and do not need additional processing, which is why __${form}__ doesn't work.
Furthermore, as I worked on this, I found out with the variable formVariables
that you cannot just pass plaintext into a th
attribute and expect it to work: it needs to be processed first, hence preprocessor.
<div class="sticky-top paginator" th:fragment="pagination(form, postUrl, formVariables)">
<nav aria-label="Page Navigation">
<ul class="pagination justify-content-center">
<li class="page-item"
th:classappend="${form.page == 1} ? disabled : ''">
<form th:action="@{${postUrl}}" th:object="${form}" method="post">
<div th:include="__${formVariables}__"></div>
<input hidden name="page" th:value="${form.page - 1}" />
<button class="page-link" th:text="#{page.previous}" />
</form>
</li>
<th:block
th:with="pageLimit=${form.totalPages > 0} ? ${form?.totalPages} : 1">
<li th:each="i : ${#numbers.sequence(1, pageLimit)}"
class="page-item" th:classappend="${i == form.page} ? active : ''">
<form th:action="@{${postUrl}}" th:object="${form}" method="post">
<div th:include="__${formVariables}__"></div>
<input hidden name="page" th:value="${i}" />
<button class="page-link" style="border-radius: 0px"
th:text="${i}" />
</form>
</li>
</th:block>
<li class="page-item"
th:classappend="${form.page >= form.totalPages} ? disabled : ''">
<form th:action="@{${postUrl}}" th:object="${form}" method="post">
<div th:include="__${formVariables}__"></div>
<input hidden name="page" th:value="${form.page + 1}" />
<button class="page-link" th:text="#{page.next}" />
</form>
</li>
</ul>
</nav>
</div>
I hope someone finds this useful!