In thimeleaf, how can I write th: each to combine rows and columns?
I want to write 4 columns in a row like this
<div class="row"> <div class="span3">Something</div> <div class="span3">Something</div> <div class="span3">Something</div> <div class="span3">Something</div> </div> <div class="row"> <div class="span3">Something</div> <div class="span3">Something</div> <div class="span3">Something</div> <div class="span3">Something</div> </div> The data size is dynamic, so it can be 4, 8 or more. it is archived in another template engine
{{#each list}} {{#if @index % 4 == 0}} <div class="row"> {{/if}} <div class="span3">{{this.name}}</div> {{#if @index % 4 == 0}} </div> {{/if}} {{/each}} but how can I archive this in the timeline? I cannot find a way because th:each is in the tag ( <div class="row"> or <div class="span3"> ) as an attribute.
MODEL CODE
List<String> data = new ArrayList<String>(); data.add("1"); data.add("2"); data.add("3"); data.add("4"); data.add("5"); data.add("6"); data.add("7"); data.add("8"); model.addAttribute("datas", data); THYMELEAF PICTURE CODE
<div th:each="data, row: ${datas}" th:with="numList=${#strings.listSplit('3,2,1,0', ',')}" th:if="${row.current} % 4 == 0" class="span3"> <span th:each="num : ${numList}" th:with="dataIndex=(${row.index} - ${num})" th:text="${datas[dataIndex]}">data</span> </div> RESULT
<div class="span3"> <span>1</span><span>2</span><span>3</span><span>4</span> </div> <div class="span3"> <span>5</span><span>6</span><span>7</span><span>8</span> </div> I used an array to solve this problem. I think you will find a better way.
I just created an account to fix the accepted answer. The accepted answer works fine if the transmitted data is transmitted by an array of consecutive integers. However, to make it work with any data structure, row.current must be changed to row.count as follows:
<div th:each="data, row: ${datas}" th:with="numList=${#strings.listSplit('3,2,1,0', ',')}" th:if="${row.count} % 4 == 0" class="span3"> <span th:each="num : ${numList}" th:with="dataIndex=(${row.index} - ${num})" th:text="${datas[dataIndex]}">data</span> </div> If you use row.current , then it uses the actual item in the list, which is great in the example shown, but not so great for any other data structure. Hope this helps.
EDIT:
I need to clarify this because the accepted answer also does not work if the number of elements in the list is not evenly divided by 4. Here is the best (although probably not ideal) solution:
<div th:each="data, row: ${datas}" th:with="numList=${ {3,2,1,0} }" th:if="${row.count % 4 == 0 or row.last}" class="span3"> <!-- Show all rows except the leftovers --> <span th:each="num : ${numList}" th:with="dataIndex=(${row.index} - ${num})" th:if="${row.count % 4 == 0}" th:text="${datas[dataIndex]}">data</span> <!-- Show the remainders (eg, if there are 9 items, the last row will have one item in it) --> <span th:each="num : ${numList}" th:with="dataIndex=(${row.index} - ${num})" th:if="${row.last} and ${row.count % 4 != 0} and ${num < row.count % 4}" th:text="${datas[dataIndex]}">data</span> </div> It can be reorganized to eliminate one of the spans, but I have to move on.
th: everyone can be used in any element in principle. So something like this:
<div class="row" th:each="row : ${rows}"> <div class="span3" th:each="name : ${row.names}" th:text="${name}">Something</div> </div> This can also be done using numbers.sequence . Set colCount to any number of columns you want:
<th:block th:with="colCount=${4}"> <div th:each="r : ${#numbers.sequence(0, datas.size(), colCount)}" class="row"> <div th:each="c : ${#numbers.sequence(0, colCount - 1)}" th:if="${r + c < datas.size()}" th:text="${datas.get(r + c)}" class="span3"></div> </div> </th:block>