initComplete fires before the table is complete?

initComplete fires before the table is complete?

smasonsmason Posts: 25Questions: 11Answers: 0

Ver. Datatable 1.10.18

I'm having a problem with timing. I want the datatable to sort upon loading based on some data. I have created a function to hide specific data.

function hideUnReadyRecords(oTable){
        $.fn.dataTable.ext.search.push(
        function(settings, data, dataIndex) {
            return $(oTable.row(dataIndex).node()).attr('data-fully-ready') == 1;
        });
    }

Upon initialization I want to trigger this function, I tried it like so:

 oTable = $(".results-table").DataTable({
                "dom": '<if<t>>',
                "bPaginate": false,
                "aaSorting": [ ],
                "initComplete": function (settings) {
                    hideUnReadyRecords(oTable);   // <-- this always fires too soon!
                }
            });

The table is supposed to be completely drawn inside initComplete right? It's not quite working for me and the function doesn't search (and remove the rows) like it should upon loading.

However, I have a checkbox elsewhere on the page that also triggers the hideUnReadyRecords function and that works fine after I check it datatables filters out the records. I put alerts in and found that the function fires before datatables is finished rendering! I can tell it's not finished because the zebra striping is not applied when the alert fires.

If there is a better way to call the hideUnReadyRecords table which does a search on load? The search criteria is a hidden data field on the <tr data-fully-ready='0' > so I'm not sure how of the syntax. All the examples I found were to search for values as if they were visible.

This question has an accepted answers - jump to answer

Answers

  • smasonsmason Posts: 25Questions: 11Answers: 0

    This works but I don't think it's very elegant. We should not have to use a setTimeout() inside the initComplete, should we?

    "initComplete": function (settings) {
          setTimeout(()=>{ $("#my-checkbox").trigger("change"); }, 1000);
    }
    
  • kthorngrenkthorngren Posts: 21,173Questions: 26Answers: 4,923
    edited December 2020 Answer ✓

    The function is applying a search plugin after the initialization. The plugin won't run until the table is drawn, ie, any search, sort, page or use of draw(). If you want the plugin to run against the loaded table data then execute it before initializing Datatables. For example:

            $.fn.dataTable.ext.search.push(
            function(settings, data, dataIndex) {
                var myTable = new $.fn.dataTable.Api( settings );  // Get API instance for table
                return $(myTable.row(dataIndex).node()).attr('data-fully-ready') == 1;
            });
    
            oTable = $(".results-table").DataTable({
                   "dom": '<if<t>>',
                   "bPaginate": false,
                   "aaSorting": [ ],
                   "initComplete": function (settings) {
                       // hideUnReadyRecords(oTable);   // <-- this always fires too soon!
                   }
               });
    

    The oTalble variable won't be available so you will need to get an instance of the API in the plugin. See the line I added. You won't need to call hideUnReadyRecords from initComplete.

    I've never seen initComplete run before Datatables initialization has completed. If you feel this is still happening please post a link to your page or a test case replicating the issue so we can debug.

    Kevin

  • allanallan Posts: 63,214Questions: 1Answers: 10,415 Site admin

    The key thing here is that without the ajax option the DataTables initialisation is synchrnous. So when initComplete is triggered oTable will not yet have been assigned. If you were using Ajax then initComplete would be able to access oTable since there is an async wait for the data from the server.

    What to do is to use this.api() inside initComplete. That will give you an API instance regardless of whether the init is async or sync - e.g.:

    initComplete: function () {
      hideUnReadyRecords(this.api());
    }
    

    That all said, I think Kevin’s solution (as usual) is correct - just add the filter before you create the table in this case. I was just filling in a bit of the tech details.

    Regards,
    Allan

  • smasonsmason Posts: 25Questions: 11Answers: 0

    Here was the solution I came up with that works based on the feedback above. I appreciate the help thank you very much.

        function hideUnReadyRecords(){
             $.fn.dataTable.ext.search.push(
              function(settings, data, dataIndex) {
                  var oTable = new $.fn.dataTable.Api( settings );  // Get API instance for table
                   return $(oTable.row(dataIndex).node()).attr('data-fully-ready') == 1;
                });
        }
        
        $(document).ready(function(){
         hideUnReadyRecords();
         oTable = $(".results-table").DataTable({
                "dom": '<if<t>>',
                "bPaginate": false 
          });
        });
    
This discussion has been closed.