Search code examples
javascriptjquerydatatablesxmlhttprequestexist-db

Repopulate a DataTables table with the result of a XHR


I'm using Jquery DataTables for displaying a long list of records:

<table id="mainTable" class="display">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>Date</th>
                        <th>Sender</th>
                        <th>Recipient</th>
                    </tr>
                </thead>
                <tbody id='mainTableRows'>
                    <tr><td><td></tr>[etc...]
                </tbody>

The table gets populated (via a XQuery, not DataTables) and intiated upon page loading:

$(document).ready(function() {$('#mainTable').DataTable({ }) } );

So far, so good. I then want the user to be able to generate new data by using a search form. The search form is something like:

<form id="advancedSearch" action="modules/advanced_search.xq" method="post" onsubmit="advancedSearch(this);">

The .xq file returns a JSON like this:

[ {
  "dateSent" : "1768-01-19",
  "personSentFullName" : "Robert Thomas",
  "personReceivedFullName" : "Richard Morris",
  "id" : "e34712"
}, {
  "dateSent" : "1768-04-23",
  "personSentFullName" : "Robert Thomas",
  "personReceivedFullName" : "Richard Morris",
  "id" : "e34716"
}, {
  "dateSent" : "1768-10-25",
  "personSentFullName" : "Robert Thomas",
  "personReceivedFullName" : "Richard Morris",
  "id" : "e34779"
}, {
  "dateSent" : "1769-01-16",
  "personSentFullName" : "Robert Thomas",
  "personReceivedFullName" : "Richard Morris",
  "id" : "e34805"
} ]

How can I use this data to repopulate my table? This is my JavaScript function called by the form submit:

function advancedSearch (oFormElement) {
event.preventDefault()

       $('#mainTable').DataTable()

               .clear()
               .draw();                       
    const oReq = new XMLHttpRequest();
    const data = new FormData(oFormElement)

    oReq.open("post", oFormElement.action, true);
    oReq.send(data);

    oReq.onreadystatechange = function () {
        if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
            const result = JSON.parse(this.responseText);

            if (result == null)
            {
                document.getElementById("result").innerHTML = "empty"
            } else {

                $('#mainTable').DataTable( {
                       ajax: result
                   } );
            }

        }   
}

}

I get a Cannot reinitialise DataTable error. I've even tried repopulating the table 'by hand', with:

for (var i = 0; i < result.length; i++) {

document.getElementById("mainTableRows").innerHTML += '<tr><td>' + result[i].id + '</td><td>' + result[i].dateSent + '</td><td>' + result[i].personSentFullName + '</td><td>' + result[i].personReceivedFullName + '</td><tr>'

I just get a discrepancy, since the table keeps reloading the old 'full' data, or I get the data in the table without pagination, or other issues which tell me that the table is not reinitialised properly. $destroy just reloads the old data, and setting serverSide: false doesn't help either.


Solution

  • I managed to do this by returning a JSON in this format (i.e. with a numeric sequence in the attribute names):

    [ {
      "0" : "e34712",
      "1" : "1768-01-19",
      "2" : "Robert Thomas",
      "3" : "Richard Morris"
    }, {
      "0" : "e34716",
      "1" : "1768-04-23",
      "2" : "Robert Thomas",
      "3" : "Richard Morris"
    }, {
      "0" : "e34779",
      "1" : "1768-10-25",
      "2" : "Robert Thomas",
      "3" : "Richard Morris"
    }, {
      "0" : "e34805",
      "1" : "1769-01-16",
      "2" : "Robert Thomas",
      "3" : "Richard Morris"
    } ]
    

    and this is my working JavaScript:

    "use strict";
    
    function advancedSearch (oFormElement) {
        event.preventDefault()
                        var table = $('#mainTable').DataTable()
                        table.clear()
    
    
        if (oFormElement.pe1id.value == '' && oFormElement.pe2id.value == '') {
            alert('You have to enter at least one person.');
            return false;
        } else {
    
            const oReq = new XMLHttpRequest();
            const data = new FormData(oFormElement)
    
            oReq.open("post", oFormElement.action, true);
            oReq.send(data);
    
            oReq.onreadystatechange = function () {
                if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
                    const result = JSON.parse(this.responseText);
    
                    if (result == null)
    
    
                    {
                            table.draw()
                    } else {
                         {
    
                            table.rows.add(result)
                             table.draw();
    
    
                    }
    
                } 
            }        
    
    
        }
    
    }