this.footer() returns NULL?

this.footer() returns NULL?

s427s427 Posts: 6Questions: 3Answers: 0

I have a table that uses dataTables in AJAX mode, with queries being performed server-side for every operation (search, sort, etc). It works fine.

I am now trying to set up individual column searching via text inputs on specific columns. Based on the example given in the official docs (https://www.datatables.net/examples/api/multi_filter.html), I arrived at this code:

    table.columns('.search-sort').every(function () {
        var that = this;
        console.log(this.footer()); // returns null
        $('input', this.footer()).on('keyup change', function () {
            if (that.search() !== this.value) {
                that.search(this.value).draw();
            }
        });
    });

(The input fields are already in the HTML code; obviously the datatable initialization is in another part of the code (it's rather complex).)

There are four .search-sort cells in the footer of the table.

My problem: the above code results in the eventlistener (keyup, change) being attached to all fields in the page, and not only the fields in the .search-sort cells. (Furthermore, each eventListener is attached four times to each field --as many as the number of search fields.)

As commented in the code above, this.footer() outputs "null" when displayed via console.log. Since this.footer() is supposed to provide a context for the jQuery selector, the fact that it returns null explains why the eventlistener are attached everywhere instead of only the current column's footer input.

So my question would be: why doesn't "this.footer()" seem to work? Any lead?

Thanks in advance.

(Of course there is a <tfoot> element in the html and it mirrors the number of columns in the <thead>)

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,330Questions: 26Answers: 4,951
    edited February 2018

    I put together this example:
    http://live.datatables.net/vuruhosa/1/edit

    I put the .search-sort class on two header columns. This is for the table.columns('.search-sort').every(function () part to work. I also put it on the same footers and adjusted the example's selector for the code that adds the text inputs, for example:
    $('#example tfoot .search-sort').each( function () {

    This seems to work.

    Kevin

  • s427s427 Posts: 6Questions: 3Answers: 0

    Thanks for taking the time to test that. One important difference is that my version works on ajax (server-side search), but I don't know how much this changes things. This makes it difficult to set a public live example (my code is behind a login form).

    Below is a more complete version of the code that I use (including HTML). I cleaned it up a little for the sake of readability. (Most notably, I removed the "rowCallback" and "drawCallback" functions, but first I checked that removing those functions has no impact on my issue).

    As you can see, the problem really boils down to this.footer() returning NULL when it is used; if I use a different jQuery selector, everything works as it is supposed to work (see comments in code).

    So my question really is what could cause this.footer() to not work as intended... ?

    HTML:

    <table id="results" width="100%" cellspacing="0">
        <thead>
            <tr>
                <th width="52"  class="no-search-no-sort"></th>
                <th width="107" class="search-sort"><span>Réf.</span></th>
                <th width="689" class="search-sort"><span>Description</span></th>
                <th width="100" class="search-sort"><span></span></th>
                <th width="100" class="search-sort"><span></span></th>
                <th width="94"  class="no-search-sort masquable"><span>Prix<br>vente</span></th>
                <th width="83"  class="no-search-sort masquable"><span>Rabais</span></th>
                <th width="83"  class="no-search-sort masquable"><span>R. qté</span></th>
                <th width="83"  class="no-search-sort masquable"><span>R. spec.</span></th>
                <th width="83"  class="no-search-sort masquable"><span>R. liq.</span></th>
                <th width="94"  class="no-search-sort masquable"><span>Prix<br>net</span></th>
                <th width="83"  class="no-search-no-sort noprint"><span></span></th>
                <th width="83"  class="no-search-sort"><span>Stock</span></th>
                <th width="83"  class="no-search-sort"><span>Quantité</span></th>
            </tr>
        </thead>
        <tfoot style="display: table-header-group;">
            <tr>
                <th></th>
                <th id="searchcol1" class="search-sort ref" ><span><input type="text" placeholder="Rechercher"></span></th>
                <th id="searchcol2" class="search-sort desc"><span><input type="text" placeholder="Rechercher"></span></th>
                <th id="searchcol3" class="search-sort var" ><span><input type="text" placeholder="Rechercher"></span></th>
                <th id="searchcol4" class="search-sort var" ><span><input type="text" placeholder="Rechercher"></span></th>
                <th class="sort"></th>
                <th class="sort"></th>
                <th class="sort"></th>
                <th class="sort"></th>
                <th class="sort"></th>
                <th class="sort"></th>
                <th></th>
                <th class="sort"></th>
                <th class="sort"></th>
            </tr>
        </tfoot>
    </table>
    
    

    JAVASCRIPT:

    $(function() {
    
        var ajaxUrl = $('#dataTablesPrefsAjaxUrl').val();
    
        var resultsTable = $('#results').DataTable( {
            "processing": true,
            "serverSide": true,
            "ajax": ajaxUrl,
            "order": [[1, 'asc']],
            "pageLength": 25,
            "stateSave": true,
            "stateDuration": 60 * 60 * 24,
            "stateSaveParams": function (settings, data) {
                delete data.search;
                delete data.start;
                for (var colId in data.columns) {
                    if (data.columns[colId].search) {
                        data.columns[colId].search.search = '';
                    }
                }
            },
            "dom": '<"datatables-before"ip>t<"datatables-after"rlp>',
            "language": {
                url: 'styles-all/datatables/fr.json'
            },
        });
    
        // Search fields on specific columns
        resultsTable.columns('.search-sort').every(function (i) {
            var that = this;
    
            console.log(this.footer()); // RETURNS NULL
    
                // THIS DOESN'T WORK BECAUSE THIS.FOOTER() IS NULL:
            // $('input', this.footer()).on('keyup change', function () {
                // TEMPORARY FIX; THIS WORKS BUT RELIES ON THE ID's OF THE CELLS:
            $('input', '#searchcol' + i).on('keyup change', function () {
    
                if (that.search() !== this.value) {
                    that.search(this.value).draw();
                }
            });
        });
    
    });
    
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Answer ✓

    Move your search code into initComplete. The issue is that since you are using Ajax, the table hasn't finished initialising (i.e. using ajax makes the DataTable also async).

    Allan

  • s427s427 Posts: 6Questions: 3Answers: 0

    Ah, yes, that was exactly it! Problem solved, thanks a lot!

This discussion has been closed.