Search code examples
javahtmlspring-bootthymeleaf

How can I get a value of an item from th:each after the page is rendered in order to send it as a request param (without using js)?


I have the following code:

        <tr th:block th:each="participant, iterStat : ${participants}">
            <td id="idField" class="table-col-id" th:text="${participant.id}">ex</td>
            <td class="table-player-name" th:text="${participant.name}">example</td>
            <td class="table-col-operation">
                <form id="newTournamentRemovePlayerForm"
                      th:action="@{/tournament/removePlayer?id={id}(id=${participant.id})}"
                      method="post">
                    <button class="player-remove-button table-action-button generic-button"
                            form="newTournamentRemovePlayerForm"
                            type="submit">Remove</button>
                </form>
            </td>
        </tr>

My goal is to send a post request to /tournament/removePlayer with the param 'id' equal to the participant.id from the row in which that button is clicked.

The table looks like this:

||id||name||action||
|1|john|remove|
|2|jane|remove|
|3|jack|remove|

However, in the current state, whichever "remove" button you click, it always sends the lowest id (eg. for the example table, clicking any remove button sends "/tournament/removePlayer?id=1").

I checked the Thymeleaf doc: https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#keeping-iteration-status

And tried using the following:

  • iterStat.current.id (sends "1"),
  • iterStat.index (sends "0"),
  • and iterStat.count (sends "1)

But those would then always send the values indicated in parentheses.

Another possibility would be sending directly the value which was filled into the "idField", but I did not manage to find any way to do that in thymeleaf either.

Is there any way to do what I need without javascript?


Solution

  • You've messed up with id attributes. id should be unique across the page, but you don't change it while iterating. Therefore each form is identified as "newTournamentRemovePlayerForm" and each button is assigned to "newTournamentRemovePlayerForm" form. Since there are many of them it fallbacks to the first one.

    You can either fix your ids or even simpler get rid of them:

        <tr th:block th:each="participant, iterStat : ${participants}">
            <td class="table-col-id" th:text="${participant.id}">ex</td>
            <td class="table-player-name" th:text="${participant.name}">example</td>
            <td class="table-col-operation">
                <form th:action="@{/tournament/removePlayer?id={id}(id=${participant.id})}"
                      method="post">
                    <button class="player-remove-button table-action-button generic-button"
                            type="submit">Remove
                    </button>
                </form>
            </td>
        </tr>
    

    Above should work as intended.