Nick Siepmann
Nick Siepmann

Reputation: 19

Thymeleaf iteration stuck at 0 in dynamically created form (Spring Boot)

I'm trying to create a table from a list phases where each row has forms that will relate to the list item phase for that row - so row 1 has a cell for "Phase 1" and then a button that will rename "Phase 1", then the next row has "Phase 2" and a button for that.

However, when I try to access the index of that list iteration from within the form it always returns 0, so the first cell of row 2 still says "Phase 2" but the form still passes the index of "Phase 1" to the HTTP request. It can definitely still see the list, because if I change it to return phaseStat.size rather than the phaseStat.indexit gives the correct number.

The cells containing the phase name work fine, it's only once I get inside the <form> tag that it gets stuck on the first item of the list. How do I get the form to keep pace with the iteration with the rest of the table?

<table class="table">
    <tr th:each="phase : ${phases}">
        <td class="table-light" th:text="${phase}"></td>
        <td>
            <form th:action="@{/tasks/phases/rename}">
                <button type="button" class="btn btn-outline-primary btn-sm" title="Rename" onclick="openForm('renamephaseform')">Rename</button>
                <div class="form-popup card mb-3" id="renamephaseform">
                    <h3 class="card-header">Rename
                        <button type="button" class="btn btn-outline-secondary btn-sm closebutton" title="Close menu" onclick="closeForm('renamephaseform')">&#9932;</button>
                        <br>
                    </h3>
                    <div class="card-body">
                        <input type="text" class="form-control" id="phasename" placeholder="Phase name" th:name="newname">
                            <button type="submit" class="btn btn-primary" title="Rename" th:name="phasenumber" th:value="${phaseStat.index}">Rename <span th:text="${phase}"></span></button>
                    </div>
                </div>
            </form>
        </td>
    </tr>
</table>

<script>
    function openForm(name) {
        document.getElementById(name).style.display = "block";
    }

    function closeForm(name) {
        document.getElementById(name).style.display = "none";
    }
</script>

Edit: The weird thing is, the iteration works perfectly fine in this example and I can't see what the difference is...

<table class="table">
    <tr th:each="album : ${albums}">
        <td class="table-light" th:text="${album.name} + ' (' + ${album.artist} + ')'"></td>
        <td>
            <form th:action="@{/index}">
                <button type="submit" class="btn btn-primary btn-sm" th:name="id" th:value="${album.id}">Open album</button>
            </form>
        </td>
</tr></table>

Upvotes: 0

Views: 174

Answers (1)

Nick Siepmann
Nick Siepmann

Reputation: 19

So, what I ended up doing that made this work (thanks to andrewJames) is including the iteration index in the form id to create a unique name.

So for the Open button I included th:attr="onclick='openForm(\'renamephaseform' + ${phaseStat.index} + '\')'", in the Closebutton th:attr="onclick='closeForm(\'renamephaseform' + ${phaseStat.index} + '\')'" and in the form tag th:attr="id='renamephaseform' + ${phaseStat.index}".

Elswhere, I've sometimes used string values for this (eg the phase name, task name etc) to make it easier to review in the Inspector.

Upvotes: 1

Related Questions