Hi Im relatively new with Spring and Thymeleaf but I am creating a disc golf CRUD app and I’m able to add a course with a Course object which has a oneToMany relation to ParList. All works fine I can add a course but a course doesnt always have 18 holes. How can I show this dynamically so a 9 hole courses table has 9 columns, a 14 – 14 columns etc?
I have tried using th:each="par, iterStat : ${course.parLists}" and trying to use iterStat.index but I can’t quite get it.
So how can I get the index of the list and use it in the hole number and display the courses par without repeating like I have below?
So my data looks like this:
Course{id=3, name='Legende Main', parLists=[ParList{parListId=10, parHole1='3', parHole2='3', parHole3='3', parHole4='3', parHole5='3', parHole6='3', parHole7='3', parHole8='3', parHole9='3', parHole10='', parHole11='', parHole12='', parHole13='', parHole14='', parHole15='', parHole16='', parHole17='', parHole18=''}]}
My HTML
<div class="container" th:each="course : ${courses}">
<div class="border">
<div id="courseDetails" class="row">
<div class="col-sm-4">
<p><strong>Course Name:</strong>
<a th:text="${course.name}"></a>
</p>
</div>
</div>
</div>
<div >
<table th:each="par, index : ${course.parLists}" id="courseInfo" class="table table-bordered w-auto">
<tr >
<th th:text="${'Hole'}"></th>
<th th:text="${}"></th>
<th th:text="${'#2'}"></th>
<th th:text="${'#3'}"></th>
<th th:text="${'#4'}"></th>
<th th:text="${'#5'}"></th>
<th th:text="${'#6'}"></th>
<th th:text="${'#7'}"></th>
<th th:text="${'#8'}"></th>
<th th:text="${'#9'}"></th>
<th th:text="${'#10'}"></th>
<th th:text="${'#11'}"></th>
<th th:text="${'#12'}"></th>
<th th:text="${'#13'}"></th>
<th th:text="${'#14'}"></th>
<th th:text="${'#15'}"></th>
<th th:text="${'#16'}"></th>
<th th:text="${'#17'}"></th>
<th th:text="${'#18'}"></th>
<th>Actions</th>
</tr>
<tr>
<td th:text="${'Par'}"></td>
<td th:text="${par.parHole1}"></td>
<td th:text="${par.parHole2}"></td>
<td th:text="${par.parHole3}"></td>
<td th:text="${par.parHole4}"></td>
<td th:text="${par.parHole5}"></td>
<td th:text="${par.parHole6}"></td>
<td th:text="${par.parHole7}"></td>
<td th:text="${par.parHole8}"></td>
<td th:text="${par.parHole9}"></td>
<td th:text="${par.parHole10}"></td>
<td th:text="${par.parHole11}"></td>
<td th:text="${par.parHole12}"></td>
<td th:text="${par.parHole13}"></td>
<td th:text="${par.parHole14}"></td>
<td th:text="${par.parHole15}"></td>
<td th:text="${par.parHole16}"></td>
<td th:text="${par.parHole17}"></td>
<td th:text="${par.parHole18}"></td>
<td>
New Course
<form action="#" th:action="@{/discgolf/saveCourse}" th:object="${newCourse}"
method="POST">
<div class="form-group">
<input type="text" th:field="*{name}"
placeholder="Course name" class="form-control mb-4 col-4">
</div>
<th:block th:object="${hole}">
<div class="container">
<div id="parRow" class="row g-0">
<div class="col">
<label>#1</label>
<input type="text" th:field="*{par}" placeholder="#1">
</div>
#2 - #17
<div class="col">
<label>#18</label>
<input type="text" th:field="*{par}" placeholder="#18">
</div>
</div>
</div>
</th:block>
<button type="submit" class="btn btn-info col-2">Save Course</button>
</form>
2
Answers
If your
parHole
would be aList<Int>
orMap<Int,Int>
then you could iterate over it or its entries withth:each
like with any list. But as you have static field names for each parHole you can’t do it and you have to be repetetive like in your example.Following Tarmo’s answer, if I were you, I would convert your parList to a List of holes, add the "Hole" and "Par" as the first values in your list so they can be included as the header rows in your table, and then iterate over them. Also then you could then use index in your :each iterator to keep track of your hole numbers