The difference betwen th:insert
and th:replace
is that th:insert
will insert the fragment as a "child" element of the element that the attribute is declared on.
With th:replace
, it replaces the element that it is declared on.
You might think that to get the exact HTML output we had in the first example, we can use th:replace
as follows:
<!-- Attention: does not work! -->
<ul>
<li th:each="user : ${users}" th:replace="fragments :: userInfoLi(${user})">
</li>
</ul>
Where userInfoLi
fragment is defined as:
<li th:fragment="userInfoLi(user)"> (1)
<div th:text="${user.name}"></div>
<div th:text="${user.country}"></div>
</li>
1 |
The root element of the fragment is <li> |
However, this does not work! The logging shows this exception:
Property or field 'name' cannot be found on object of type 'java.lang.String'
Thymeleaf processes the th:insert
and th:replace
attributes before the th:each
.
So in our example, due to the th:replace
, Thymeleaf generates this:
<ul>
<li>
<div th:text="${user.name}"></div>
<div th:text="${user.country}"></div>
</li>
</ul>
Because the <li>
in index.html
is replaced with the <li>
from the fragment, the th:each
is no longer there.
As a consequence, the user
variable is unknown and Thymeleaf gives an error processing the template.