1

I'm having a problem with a Thymeleaf loop where it is returning the wrong object within a nested div. Where I expect it to return the object that corresponds to the sequential table row, instead it returns the first object in the loop. Code is posted below with comments:

<table class="striped responsive-table">
  <thead>
  <th>name</th>
  <th>url</th>
  <th>updated</th>
  <th>author</th>
  </thead>
  <tbody>

  <!-- THE BEGINNING OF THE LOOP-->
  <tr th:each="page : ${pages}">

    <!-- THIS RETURNS THE CORRECT OBJECT AND ATTRIBUTE-->
    <td><strong><span th:text="${page.name}"></span></strong></td>
    <td><a th:href="'/p-' + ${page.url}" class="waves-effect waves-light explode">
      <span th:text="'/p-' + ${page.url}"></span></a></td>
    <td th:text="${page.updated}"></td>
    <td th:text="${page.author.getUsername()}"></td>
    <td style="text-align: right;">
      <a class="btn waves-effect waves-light" th:href="'page-edit-' + ${page.id}">edit</a>
      <a class="waves-effect waves-light btn btn-flat btn-delete view"
         onclick="$('#modal1').modal('open');">delete</a>

      <!-- Modal Structure -->
      <div id="modal1" class="modal">
        <div class="modal-content center">
          <h4 style="color: darkred">Are you sure?</h4>

          <!-- HERE IS MY PROBLEM: THIS RETURNS THE FIRST OBJECT IN THE LOOP EVERY TIME -->
          <p th:text="'Confirm that you want to delete this page: ' + ${page.name}"
             style="color: darkred"></p>
        </div>
        <div class="modal-footer">
          <a href="#" class=" modal-action modal-close waves-effect waves-green btn-flat">CANCEL</a>
          <a th:href="'/page-delete-' + ${page.id}"
             class=" modal-action modal-close waves-effect waves-red btn-flat">DELETE</a>
        </div>
      </div>

      <script>
          $(document).ready(function () {
              $('#modal1').modal();

          });
      </script>
    </td>
  </tr>
  </tbody>
</table>

How I can get around this problem?

2
  • As a side note, it's more idiomatic to write page.author.username (and to use DELETE instead of some ad-hoc "delete URL"). Commented Dec 29, 2017 at 21:50
  • Got it, thanks for the feedback @chrylis. Commented Dec 29, 2017 at 21:56

2 Answers 2

1

Your problem is that you're using an id attribute, which is required to be unique in the entire DOM, inside a loop. The HTML you produce (which you should have inspected directly) has duplicates, and when your JavaScript fires, the browser finds the first matching element and returns it.

Instead, you need to do something like set a data attribute on the tr or button and have the JavaScript click handler pass the ID to the modal.

Sign up to request clarification or add additional context in comments.

1 Comment

That makes sense about the id attribute. I know it's a lot to ask, but I'm not learned with JS yet, can you provide an example of how I would alter my script so that I can ditch the use of the id? This is an example ripped straight from Materialize.
0

Thanks @chrylis for leading me down the right path. This is my solution.

                            <a class="waves-effect waves-light btn btn-flat btn-delete view" th:onclick="'$(\'#row-' + ${page.id} + '\').modal(\'open\');'">delete</a>
                        <!-- Modal Structure -->
                        <div th:id="'row-' + ${page.id}" class="modal">
                            <div class="modal-content center">
                                <h4 style="color: darkred">Are you sure?</h4>
                                <p th:text="'Confirm that you want to delete this page: ' + ${page.name}" style="color: darkred"></p>
                            </div>
                            <div class="modal-footer">
                                <a href="#" class=" modal-action modal-close waves-effect waves-green btn-flat">CANCEL</a>
                                <a th:href="'/page-delete-' + ${page.id}" class=" modal-action modal-close waves-effect waves-red btn-flat">DELETE</a>
                            </div>
                        </div>

                        <!-- Modal Trigger -->

                        <script th:inline="javascript">
                            /*<![CDATA[*/

                            $(document).ready(function() {
                                $(/*[['#row-' + ${page.id}]]*/).modal();
                            });

                            /*]]>*/
                        </script>

1 Comment

As a suggestion, if you're sticking with id (instead of data-row-id), it's probably a good idea to use a prefix ('row-' + page.id) to avoid collisions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.