5
votes

I have a function that creates a datatable. On page load the datatable is created and drawn. Now, when I have a form submit to make a search on a table, I call the same function. First I make an instance of the datatable, I call the clear function then I call the function to recreate it.

Here is how I create the datatable for the first time, which works just fine:

    $(window).load(function () {


        var table = UpdateTableCompany(null, null);
        .....

Here is the function which manages the datatable:

    function UpdateTableCompany(val, search_field)
{
    $('#tablePubDev').DataTable().clear();
    var table = $('#tablePubDev').DataTable({
        destroy: true,
        searching: false,
        "lengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
        "pageLength": 5,
        "columnDefs": [
            {
                "render": function (data, type, row) {


                    var text = '<div class="form-group">' +
                            '<div class="checkbox-nice center" style="cursor: default; height:100px;">' +
                            '<img  src="/application/assets/img/pub_devs/logos/' + row['c']['logo'] + '" style="max-height:100%; max-width: 100%;"/>' +
                            '</div>' +
                            '<div class="checkbox-nice text-center" style="cursor: default">' +
                            '<strong >Id: ' + pad(data, 11) + '</strong>' +
                            '</label>' +
                            '</div>' +
                            '</div>';


                    return text;
                },
                "targets": 0,
            },
            {
                "render": function (data, type, row) {


                    var text = '<div class="form-group">' +
                            '<div class="checkbox-nice center" style="cursor: default; height:100px;"><p class="center" style="font-size: 150%; font-weight: bold;">' +
                            row['c']['descr'] +
                            '</p></div>' +
                            '</div>';


                    return text;
                },
                "targets": 1,
            },
            {
                "render": function (data, type, row) {

                    var add_text1 = '';
                    var checked1 = '';
                    var add_text2 = '';
                    var checked2 = '';

                    if (data != null && data > 0) {

                        checked1 += 'checked="checked"';
                    } else
                        add_text1 += 'buttonDisabled ';

                    if (row['c']['developer'] != null && row['c']['developer'] > 0) {

                        checked2 += 'checked="checked"';
                    } else
                        add_text2 += 'buttonDisabled ';


                    var text = '<div class="form-group">' +
                            '<div class="checkbox-nice ' + add_text1 + '" style="cursor: default">' +
                            '<input type="checkbox" ' + checked1 + ' disabled="disabled" id="checkbox-1">' +
                            '<label for="checkbox-1">' +
                            'Publisher ' +
                            '</label>' +
                            '</div>' +
                            '<div class="checkbox-nice ' + add_text2 + '" style="cursor: default">' +
                            '<input type="checkbox" id="checkbox-2" ' + checked2 + ' disabled="disabled">' +
                            '<label for="checkbox-2">' +
                            'Developer' +
                            '</label>' +
                            '</div>' +
                            '</div>';


                    return text;
                },
                "targets": 3,
            },
            {
                "render": function (data, type, row) {
                    var text = '<td style="width: 20%;">' +
                            //'<a href="#" class="table-link">' +
                            //'<span class="fa-stack">' +
                            //'<i class="fa fa-square fa-stack-2x"></i>' +
                            //'<i class="fa fa-search-plus fa-stack-1x fa-inverse"></i>' +
                            //'</span>' +
                            //'</a>' +
                            '<a href="#" class="table-link updatePubDev" data-modal="modal-11">' +
                            '<span class="fa-stack">' +
                            '<i class="fa fa-square fa-stack-2x"></i>' +
                            '<i class="fa fa-pencil fa-stack-1x fa-inverse"></i>' +
                            '</span>' +
                            '</a>' +
                            '<span class="fa-stack table-link danger deletePubDev">' +
                            '<i class="fa fa-square fa-stack-2x"></i>' +
                            '<i class="fa fa-trash-o fa-stack-1x fa-inverse"></i>' +
                            '</span>' +
                            '</td>';


                    return text;
                },
                "targets": 4,
            }
        ],
        "columns": [
            {"data": "c.idpubdev", "name": "c.idpubdev"},
            {"data": "c.descr", "name": "c.descr"},
            {"data": "c.date_founded", "name": "c.date_founded"},
            {"data": "c.publisher", "name": "c.publisher"},
            {"data": "c.date_founded", "name": "c.date_founded"},
            {"data": "c.developer", "name": "c.developer", "visible": false, "searchable": false},
            {"data": "c.logo", "name": "c.logo", "visible": false, "searchable": false},

        ],
        "order": [[0, false], [1, 'asc'], [2, 'asc'], [3, 'asc']],

        "displayLength": 3,
        serverSide: true,
        "ajax":
                {
                    "url": "/pubdev/search/",
                    "type": "POST",
                    "data": function (d) {
                        if (val)
                            d.val = val;
                        if (search_field)
                            d.search_field = search_field;
                    }

                },
        error: function (request, status, error) {
            alert('Unable to update table contents');
            console.log(request);
            console.log(status);
            console.log(error);
        },

    });

    return table;
}

Here instead is the submit of the form which executes the search function:

 $("#search_form").submit(function (e) {
            e.preventDefault();

            var search_key = $.trim($('#val').val());
            var search_field = 'c.descr like ';

            table = $('#tablePubDev').DataTable();

            table.clear();

            table = UpdateTableCompany(search_field, search_key);

        });

I am currently using the minified format of jquery version v1.10.2 The version of datatable is 1.10.4

This is the error I get in the console enter image description here

I tried an experiment: I did not load the datatable in document ready, so I made a search submit to load the datatable , and it worked! Of course if I do a second search then the same error occurs, so the problem has to do with the recreation of datatable. All the back end code (php) works correctly and gives the desired results.

Here is the table in html

 <div class="main-box no-header clearfix">
                    <div class="main-box-body clearfix">
                        <div class="table-responsive">
                            <table id="tablePubDev" class="table user-list table-hover">
                                <thead>
                                    <tr>
                                        <th>Company</th>
                                        <th>Name</th>
                                        <th><span>Listed Games</th>
                                        <th>Type</th>
                                        <th>Actions</th>
                                    </tr>
                                </thead>
                                <tbody>

                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

I have tried using the unminified version of datatable (v 1.10.12) and I got still and error but now it says his:

TypeError: headerCells[i] is undefined

headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !==...
    // Clone the table header and footer - we can't use the header / footer
        // from the cloned table, since if scrolling is active, the table's
        // real header and footer are contained in different table tags
        tmpTable.find('thead, tfoot').remove();
        tmpTable
            .append( $(oSettings.nTHead).clone() )
            .append( $(oSettings.nTFoot).clone() );

        // Remove any assigned widths from the footer (from scrolling)
        tmpTable.find('tfoot th, tfoot td').css('width', '');

        // Apply custom sizing to the cloned header
        **headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0]** ); <-- This is where the error occurs <--

        for ( i=0 ; i<visibleColumns.length ; i++ ) {
            column = columns[ visibleColumns[i] ];

            headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
                _fnStringToCss( column.sWidthOrig ) :
                '';

            // For scrollX we need to force the column width otherwise the
            // browser will collapse it. If this width is smaller than the
            // width the column requires, then it will have no effect
            if ( column.sWidthOrig && scrollX ) {
                $( headerCells[i] ).append( $('<div/>').css( {
                    width: column.sWidthOrig,
                    margin: 0,
                    padding: 0,
                    border: 0,
                    height: 1
                } ) );
            }
        }

        // Find the widest cell for each column and put it 

UPDATE:

I think I know why this is happening, although I still need to find a fix for this. It just so happens that When I define my columns in the Datatable instantiation:

   "columns": [
            {"data": "c.idpubdev", "name": "c.idpubdev"},
            {"data": "c.descr", "name": "c.descr"},
            {"data": "c.date_founded", "name": "c.date_founded"},
            {"data": "c.publisher", "name": "c.publisher"},
            {"data": "c.date_founded", "name": "c.date_founded"},
            {"data": "c.developer", "name": "c.developer", "visible": false, "searchable": false},
            {"data": "c.logo", "name": "c.logo", "visible": false, "searchable": false},

These need to be exactly as many as the table headers that I included in my html page

                            <thead>
                                    <tr>
                                        <th>Company</th>
                                        <th>Name</th>
                                        <th><span>Listed Games</th>
                                        <th>Type</th>
                                        <th>Actions</th>
                                    </tr>
                                </thead>

In this case I have 5 table headers and 7 data column definitions (two have visible = false). When I used them in an older project, all I had to do was set the "visible" property to false so that they wouldn't be mapped to a table header, but here it doesn't seem to work... Why do you think that would happen? I sthere a way to work around it?

3
Well I think I do use php in the back end but I feel that the problem doesn't have to do with php, but is in jquery or datatable pluginSalvo
Anyone, please help. I've put everything that I think could be of use.Salvo

3 Answers

14
votes

Ok, I actually solved this problem! So there is a bug (feature ?? ) in the datatable.js plugin. When it tries to autowidth the columns, it needs to have as many headers as there are data columns defined. So if you have 7 column definitions and you have only 5 headers defined, the code will fail with a null pointer exception. One way to work around this is to set the autowidth parameter to false (by default it is true).

   function UpdateTableCompany(val, search_field)
    {

        var table = $('#tablePubDev').DataTable({
            'destroy': true,
            searching: false,
            'info': false,
            paging: true,
            retrieve: false,
            processing: true,
            "autoWidth": false, // This parameter must be set to false
          ......

By doing this you avoid the call to the functon which actually tries to do the autowidth. So by avoiding that part of the datatable code, you wont have the error described.

0
votes

Instead of recreate the table every time you click the #search_form button, you should only reload the table datasource. Try the following:

First, let's change your function a little, so it will not be used to update your table anymore, but to create it (it will be called only once). Remove the search parameters as follows:

from function UpdateTableCompany(val, search_field)

to function UpdateTableCompany()

you may want to rename your function as well:

function CreateTableCompany() {
...

Now, Inside your "ajax" function, change the way you obtain the values. Make it get the values dinamically, something like:

d.val = $('#val').val().trim();
d.search_field = $('#search_field').val().trim();

Now you need to create your table variable outside the load scope, so it can be accessed from other functions:

var table;
$(window).load(function () {
    table = CreateTableCompany();
...

Finally, remove the content of the submit function (except the e.preventDefault();)

It should look like this:

$("#search_form").submit(function (e) {
    e.preventDefault();
    table.ajax.reload();
});

I think this will do the trick. I hope it helps.

0
votes

Sometimes this error can be occurred due to difference in no of columns of in thead and datatable columns.