htmlspringthymeleafspring-thymeleaf

Thymeleaf cannot use th:each with th:replace in the same tag


I need to do the following

<tr th:fragment="rowFragment(rowObject)">
            <td th:each="cellObject : ${rowObject.getCellObjects()}" th:replace="~{::cellFragment(${cellObject})}"></td>
        </tr>

In leymans terms for each object in a list construct a new cell. Each cell itself is formed via a thymleaf fragment hence th:replace with th:each.

I noticed that this code does technically "work" with th:each and th:insert, however these two in conjunction cause Thymeleaf to render the first defined in the alongside the fragment (essentially resulting in two elements when there only needs to be one. Hence my desire to use th:replace.

However th:replace along side th:each causes weird null pointer exceptions that I am unable to pinpoint. My best guess is that th:replace removes the th:each from the element(and thus the rowObject variable) and then attempts to pass such void/null rowObject into the fragment causing the null pointer error.

any suggestions?


Solution

  • According to Thymeleaf Attribute Precedence insert and replace will work before each operator. This is why cellObject is not defined yet when processing replace. To change the order of processing, you would need to separate the attributes and process each before replace. To do this you may want to use th:block synthetic tag and your code may look like ...

    <tr th:fragment="rowFragment(rowObject)">
        <th:block th:each="cellObject : ${rowObject.getCellObjects()}">
           <td th:replace="~{::cellFragment(${cellObject})}"></td>
        </th:block>
    </tr>
    

    Please note, I didn't run this code and it is for demonstration of the idea only.