0

I'm using Spring Boot and JQuery to refresh a fragment in my web page. I call for the fragment to be replaced with:

$.get(urlString, function (fragment) { // get from controller
    $("#resultTable").replaceWith(fragment);
});

The fragment is then updated with a new table as a Thymeleaf template shown here:

<span id="resultTable">
<th:block th:if="${table} != null and ${tableHead} != null">
    <table id="main" class="display">
        <thead>
            <tr>
                <th:block th:each="columnHeader: ${tableHead}">
                    <td th:text="${columnHeader}"></td>
                </th:block>
            </tr>
        </thead>
        <tbody>
            <th:block th:each="row : ${table}">
                <tr>
                    <th:block th:each="column : ${row}">
                        <td th:text="${column}"></td>
                    </th:block>
                </tr>
            </th:block>
        </tbody>
    </table>
</th:block>

<th:block th:if="${error} != null and ${error} == true">
    <div class="errorBox">
        <p th:text="${errorMsg}"></p>
    </div>
</th:block>

To make it more readable, I'm then using JQuery to update the table to use Data Table

$('#main').DataTable({
    paging: false
});

However, the table isn't reworked by Data Tables yet, because the table isn't actually updated when the above code block is run. I have these two JQuery statements run one after the other in the script, and if I delay the process for 5 seconds, it works as expected. Issue is, if the fragment takes longer than that to get, which it very well could since I'm processing SQL Queries, the table then doesn't get the Data Tables update. So, I want to find a way to halt the script until the fragment has actually loaded.

To be clear, the withReplace completes before the table is added to the page, so something else completes the replacement. I just need a way to check if the table has been updated again after the withReplace runs.

JAF
  • 31
  • 9
  • first, I think you tagged your question wrong, isn't it javascript instead of java? – Calvin Nunes Jan 22 '20 at 20:56
  • Does this answer your question? [jQuery wait for replaceWith to finish before executing](https://stackoverflow.com/questions/24429210/jquery-wait-for-replacewith-to-finish-before-executing) – Calvin Nunes Jan 22 '20 at 20:56
  • No, in the case of that question the div has actually been updated, what's returned in this scenario isn't actually updated. – JAF Jan 22 '20 at 21:05
  • Ok, but I really think that the problem is not to wait for `.replaceWith()`, since it is *not* asynchronous (as stated in the question I linked above) – Calvin Nunes Jan 22 '20 at 21:06
  • I only know what I'm experiencing here, as my experience with JQuery is limited. But the table doesn't get updated to use the Data Table classes unless I add a delay, which makes me think either it is asynchronous, or it hands it off to another process that is asynchronous. – JAF Jan 22 '20 at 21:09
  • after `$("#resultTable").replaceWith(fragment);` add `$("#resultTable").DataTable({ paging: false });` ? – Dirk Deyne Jan 22 '20 at 21:32
  • Data Tables needs to be run against the actual table based on ID: https://datatables.net/manual/installation So it needs to be $("#main"). I tried just to be sure, but no dice – JAF Jan 22 '20 at 21:35

1 Answers1

0

I made a workaround for this where I appended a special class name to a div at the end of thymeleaf template that only shows up upon a successful completion. I then have a triggered custom event that went off and checked for the presence of this class every few seconds, using a delay.

I don't understand the behind the scenes magic going on here, but what I observed was like there was only one thread running, and a while loop without a delay that checked for the existence of the class would essentially live lock the script, so that the table would never get generated, and the class it looks for never inserted.

Anyway, here's the JQuery scripts I used:

<script>
    $(document).on('click', function(event) {
        var editor = ace.edit("editor");
        if (event.target.id == "querySubmit" && !editor.getReadOnly()) {

            editor.setReadOnly(true);
            editor.setTheme("ace/theme/clouds");

            var urlString = "runQuery?sqlField=" + encodeURI(editor.getValue()) +
                "&dbSelection=" + encodeURI($("#dbSelection  option:selected").text());

            $.get(urlString, function (fragment) { // get from controller
                $("#resultTable").replaceWith(fragment);
            });

            $(document).trigger("one:queryReturned");
        }
    });
</script>
<script>
    $(document).on("one:queryReturned", function(event) {
        if($(".complete").length === 0){
            setTimeout(function () {
                $(document).trigger("one:queryReturned");
            }, 3000);
        }else{

            var complete = $(".complete");
            complete.removeAttr("class");

            var editor = ace.edit("editor");
            editor.setReadOnly(false);
            editor.setTheme("ace/theme/twilight");

            $("#main").DataTable({
                paging: false
            });
        }
    });
</script>

Feel free to remove the timeout if you want to experience that for yourself.

JAF
  • 31
  • 9