How to pass object to modal dialog in Thymeleaf?

Viewed 5816

I have a thymeleaf page that shows database content (persons) in a table.

<tr id="tableBody">
    <td th:text="${row.id}"/>
    <td th:text="${row.firstname}"/>
    <td th:text="${row.lastname}"/>
    <td>
        <button data-toggle="modal" data-target="#editModal" th:data-row="${row}">DEL</button>
    </td>
</tr>

The last column should be a button that deletes the row. But prior, show a modal dialog with the data being deleted.

Question: how can I pass the the full row person object to a modal dialog?

I started as follows, but I'm missing how I could actually pass the person object from the clicked row into the modal dialog as an object (so that I can show the person fields in the modal dialog again).

The following is kind of pseudo code:

<div class id="editModal" ...>
  <div class="modal-body">
    <div class="modal-body">
       You are about to delete: <div th:text="${row.firstname}"/> <div th:text="${row.lastname}"/>

       <form action="#" th:action="@{/delete/{id}" th:object="${row}" method="delete">
          <input type="text" hidden="true" th:field="${row.id}">
       </form>
    </div>

    <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="submit" class="btn btn-primary" th:href="@{/delete/{id}(id=${row.id})}" th:method="delete">Remove</button>
    </div>
  </div>
</div>
2 Answers

Pure thymeleaf

To do it in pure thymeleaf, you would need to create a dialog for every row in the table with a unique id, and open the dialog associated to the row being deleted.

Example modals:

<div th:each="row : ${rows}" th:attr="id=${'editModal' + row.id}">
  <div class="modal-body">
    <div class="modal-body">
       You are about to delete: <div th:text="${row.firstname}"/> <div th:text="${row.lastname}"/>

       <form action="#" th:action="@{/delete/{id}" th:object="${row}" method="delete">
          <input type="text" hidden="true" th:field="${row.id}">
       </form>
    </div>

    <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="submit" class="btn btn-primary" th:href="@{/delete/{id}(id=${row.id})}" th:method="delete">Remove</button>
    </div>
  </div>
</div>

And the button which opens the dialog becomes:

<button data-toggle="modal" th:attr="data-target=${'#editModal'+row.id}" data-row="${row}">DEL</button>

With javascript

If you can use javascript, I would recommend creating only a template of the modal dialog using thymeleaf, then clone it and and populate it dynamically.

Example modal:

<div class id="editModalTemplate">
  <div class="modal-body">
    <div class="modal-body">
       You are about to delete: <div data-value="firstname"/> <div data-value="lastname"/>

       <form action="#" th:action="@{/delete/_id_}" method="delete">
          <input type="text" hidden="true" name="id">
       </form>
    </div>

    <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
        <button type="submit" class="btn btn-primary" th:href="@{/delete/{id}(id='_id_')}" th:method="delete">Remove</button>
    </div>
  </div>
</div>

The delete button:

<button class="btn-delete" data-id=${row.id} data-firstname="${row.firstname}" data-lastname="${row.lastname}">DEL</button>

Javascript (using jQuery implementation as example):

$('.btn-delete').click(function(){
    //clone dialog and remove ids to ensure uniqueness
    var $modal = $('#editModalTemplate').clone().removeAttr('id');

    //apply custom values where needed
    var $btn = $(this);
    var rowId = $btn.attr('data-id');
    var firstname = $btn.attr('data-firstname');
    var lastname = $btn.attr('data-lastname');

    $modal.find('[data-value="firstname"]').text(firstname );
    $modal.find('[data-value="lastname"]').text(lastname );
    $modal.find('[name="id"]').val($btn.attr('data-id'));
    $modal.find('form').attr('action').replace('_id_', rowId);     
    $modal.find('button[type="submit"]').attr('href', $modal.find('button[type="submit"]').attr('href').replace('_id_', rowId);

    //show dialog
    $modal.modal();
});

The ease solution I found, hope it helps with who is struggling, the trick is to put the modal inside the same loop of the table or div, and creating and dynamic "id" with the attribute sentence of thymeleaf, like is explained in this page for an older version:

    <tr th:each="user: ${users}">
        <td ><a data-bs-toggle="modal" data-row="${user}"
                th:attr="data-bs-target='#modal-warning'+${user.id }">Inactivate</a> 
    
    <!--  MODAL -->
  <div th:fragment="modal" class="modal fade" th:id="modal-warning+${user.id }" tabindex="-1"

You could also check my original post here

Related