Getting original, unmodified thead elements

Getting original, unmodified thead elements

datpetedatpete Posts: 6Questions: 1Answers: 0

I am new here, so please bear with me :)

TL;DR; Can I get the undecorated thead (and tfoot) elements of a table using the DataTables API?

I am struggling with the following (example difficult to extract from my code):

I have a table using datatables 2.0. On a regular basis I use ajax to fetch the server-side version of the table, since other processes may cause changes to the table. I would like to highlight cells, that are changed (if shown in the datatable search filtering). So I run through each of the td and th elements in the datatable rows and compare them with the corresponding ones from the server, and if changed, I update the cells using cell.data() and animate the highlight.

The problem is, that the td's and th's in thead and tfoot may also have changed on the server, and to update the header/footer cells and highlight the changes, I need to compare with the elements in client table thead and tfoot.

However, the cells in the DataTable() enabled table thead and tfoot are decorated with extra attributes, but the server side elements are not. So for comparison I would like to obtain the underlying, undecorated, elements for the thead and tfoot of the table.

I have tried table().header().
And I have tried cloning the table, and calling destroy() on the clone, and then use the thead and tfoot from the resulting table.
But in both approaches, there are still remains of datatable decorations on the elements.

I have seen suggestions for saving a clone of the table thead and tfoot before Datatable() initialization, but this is not easy for me in the current code base, since initialization of the table and handling of the background update is done in different modules, and I want to implement this for a lot of unrelated tables.
I saw a suggestion then, to store the original thead together with the DataTable()-initialized table:

var originalTheadContent = $('#myTable thead').html();

var table = $('#myTable').DataTable({
   initComplete: function(settings, json) {
      settings.originalTheadContent = originalTheadContent;
   }
});

// Later, when you need to access the original `thead` content
var originalThead = table.settings()[0].originalTheadContent;
console.log("Original thead content:", originalThead);

This approach might work, but I would have to add this to all initializations of tables, and also to update the settings every time a background change is detected, so before attempting this approach, I would like to ask you experts, if I am missing a much simpler solution?

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin

    DataTables will use the original elements provided for the table header and footer and add the extra attributes to them. So they are the original DOM nodes, just modified with extra attributes.

    How are you doing your comparison - could you just limit it to a specific attribute, or the content of the cell perhaps?

    Allan

  • datpetedatpete Posts: 6Questions: 1Answers: 0

    I am already comparing just specific attributes and the content. But for the thead, the content of TD and TH seems to be decorated too.

    See this complete example

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>DataTables Example</title>
        <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
        <link href="https://cdn.datatables.net/v/dt/dt-2.1.4/datatables.min.css" rel="stylesheet">
        <script src="https://cdn.datatables.net/v/dt/dt-2.1.4/datatables.min.js"></script>
    </head>
    <body>
    
        <table id="myTable">
            <thead>
                <tr>
                    <th><a href='https://disney.com'>Name</a></th>
                    <th>Position</th>
                    <th>Office</th>
                    <th>Age</th>
                    <th>Start date</th>
                    <th>Salary</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Tiger Nixon</td>
                    <td>System Architect</td>
                    <td>Edinburgh</td>
                    <td>61</td>
                    <td>2011/04/25</td>
                    <td>$320,800</td>
                </tr>
            </tbody>
        </table>
    
        <script>
            $(document).ready(function() {
                var table = $('#myTable').DataTable();
                var firstTh = $(table.table().header()).find('tr th').first();
                console.log("First th of header() content:", firstTh.html());
                console.log("Second th of header() content:", firstTh.next().html());
    
                var clonedTable = $('#myTable').clone();
                clonedTable.DataTable().destroy();
                var firstClonedTh = clonedTable.find('thead tr th').first();
                console.log("First th of cloned and destroyed thead content:", firstClonedTh.html());
                console.log("Second th of cloned and destroyed thead content:", firstClonedTh.next().html());
            });
        </script>
    
    </body>
    </html>
    

    For both attempts to get the elements from the datatable itself, it returns decorated content. E.g.

    Second th of header() content: <span class="dt-column-title" role="button">Position</span><span class="dt-column-order"></span>
    

    I would have expected just "Position".

    So checks for server-side changes is somewhat complicated.
    And I will have to somehow store the original thead before initializing DataTables() to be able to check for differences?

  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Answer ✓

    Yes, it will insert extra elements into the header cells to display the sorting icons (and potentially other things in future).

    And I will have to somehow store the original thead before initializing DataTables() to be able to check for differences?

    My point is that DataTables is using the original thead and its rows/cells. It modifies the header in the document.

    If you do:

    var thead = document.querySelector('thead');
    var table = new DataTable('table');
    
    console.log(
      table.table().header() === thead
    );
    

    it would show true.

    You could use column().title() if you have just the title text to check.

    Allan

  • datpetedatpete Posts: 6Questions: 1Answers: 0

    OK thanks - I just needed to know if there was any way to get the original element value directly from the initialized datatable, but I understand, that this is not possible. I will seek an alternative then. Thank you!

  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin

    I suppose one option might be to write the value of the element to an attribute of the element before the DataTables initialisation. Then you can use that as the basis for comparison.

    Allan

  • datpetedatpete Posts: 6Questions: 1Answers: 0

    Hi thanks, yes that might be one solution.

    I think, though, that I will instead try to pack the content of the cell inside a span with a distinctive class, and just compare those span elements if found inside the html().

    In some of the heading cells I have buttons with titles. Both presence, the function and the titles of such buttons may change depending on the state of the underlying data, and that is a bit tricky to "store" in an attribute.

Sign In or Register to comment.