Unable to disable/enable button on checkbox selection using ajax.url().load()

Unable to disable/enable button on checkbox selection using ajax.url().load()

markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

Hello,

I am having trouble disabling/re-enabling a button that I've created outside of my datatable. I have 3 datasets that I displaying using the ajax request found here https://datatables.net/reference/api/ajax.url(). I used a call similar to the one from the example table.ajax.url( 'newData.json' ).load();. I use a nav menu I have created on trigger the dataset load on a jQuery click event handler. When the page initially loads, I have no problem disabling the button through a check selection. The problem occurs when I load a different dataset. The clicks on the checkboxes do not register when inspecting it through the browser.

To add a checkbox, I do the following within my column:

'render': function (data, type, full, meta){
return '<input class="doc-selection-row" name="doc-selection-row" type="checkbox">';
},

I also have an init function that I used to disable my button on dataload:

initComplete: function () {
$('#account-div input:checkbox').change(function(){
$("#delete-btn").prop("disabled", $('#account-div input:checkbox:checked').length ===0);
});
}
}

and Finally, these are my click handlers to navigate between the data:

$("#finance").click(function() {
table.ajax.url('/finance/docs').load();
});

$("#accounting").click(function() {
table.ajax.url('/accounting/docs').load();
});

$("#sales").click(function() {
table.ajax.url('/sales/docs').load();
});

Again, when I initially load the page, I have no problem disabling and enabling the button on a checkbox selection. The problem is when i navigate to another dataset is where I am unable to do what I need to do. Also, When navigating back to the default dataset, the button disable/enable no longer works. I need to reload the page.

Thanks again!

This question has accepted answers - jump to:

Answers

  • kthorngrenkthorngren Posts: 20,379Questions: 26Answers: 4,781
    Answer ✓

    Sounds like you are running into the issue described in this faq.

    Kevin

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    Thanks for pointing out the faq. I was able to fix the issue.

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    I am having one more problem inline with this issue. I created a drop down on the date column using an init function and something similar happens. The options that load on the drop down filter are only from the initial data load. When navigating to other data sets, the options do not get updated. The same options from the original data load only gets displayed.

    ```
    $(document).ready(function() {

    var table = $('#table').DataTable( {
        ajax: {
            url: '/docs/accounting',
            dataSrc: ''
        },
        info: false,
        order: [[ 2, "asc" ]],
        paging: false,
        scrollX: true,
        scrollY: 500,
        searching: true,
        scrollCollapse: true,
        columns: [
            {
                'targets': 0,
                'searchable':false,
                'orderable':false,
                'className': 'dt-body-center',
                'render': function (data, type, full, meta){
                    return '<input class="select" name="selection" type="checkbox">';
                },
                width: "5%"
            },
            {
                data: "id",
                width: "15%"
            },
            {
                data: "department",
                width: "25%"
            },
            {
                data: "date",
                //convert time from milliseconds to date
                render: function(jsonDate) {
                    //convert numeric month into string
                    var date = new Date(jsonDate);
                    var options = { month: 'long', year: 'numeric' };
                    var dateToString = date.toLocaleDateString("en-US", options);
                    return dateToString;
                },
                orderable: false,
                width: "15%"
            },
            {
                data: "file",
                render: function( data ) {
                    var message = "No file";
                    return message
                },
                sortable: false,
                searchable: false,
                class: "dt-body-center",
                width: "15%"
            }
        ],
    
    
        initComplete: function () {
            //Drop down filter replaces the header title for Date
            this.api().columns([3]).every( function () {
                var column = this;
                var select = $('<select class="date-filter"><option value="">Date</option></select>')
                    .appendTo( $(column.header()).empty() )
                    .on( 'change', function () {
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );
    
                        column
                            .search( val ? '^'+val+'$' : '', true, false )
                            .draw();
                } );
                column.data().unique().sort().each( function ( d, j ) {
                    //convert milliseconds to date
                    var date = new Date(d);
                    var options = { month: 'long', year: 'numeric' };
                    var dateToString = date.toLocaleDateString("en-US", options);
    
                    //reformat date and fill options with new date
                    select.append( '<option value="'+dateToString+'">'+dateToString+'</option>' )
                } );
            } );
        }
    
    } );
    
    $("#finance").click(function() {
        table.ajax.url('/docs/finance').load();
    });
    
    $("#accounting").click(function() {
        table.ajax.url('/docs/accounting').load();
    });
    
    $("#sales").click(function() {
        table.ajax.url('/docs/sales').load();
    });
    

    } );

  • colincolin Posts: 15,166Questions: 1Answers: 2,588

    Hi @markMathews1989 ,

    That's because all your work is in the initComplete function, and this is only called on first load. It you want it on each load, the best place to recalculate would be in xhr,

    Cheers,

    Colin

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    Thanks for the reply Colin. I found the xhr event a few minutes after I made this post. However, I am having trouble using it. I tried to take everything from the init and pasted it into the xhr event that I set. I also tried to replace this with the table variable. Not sure what to do.

    var table= $('#table').on('xhr.dt', function ( e, settings, json, xhr ) {
            this.api().columns([3]).every( function () {
                    var column = this;
                    var select = $('<select><option value="">Date</option></select>')
                        .appendTo( $(column.header()).empty() )
                        .on( 'change', function () {
                            var val = $.fn.dataTable.util.escapeRegex(
                                $(this).val()
                            );
    
                            column
                                .search( val ? '^'+val+'$' : '', true, false )
                                .draw();
                        } );
    
                    column.data().unique().sort().each( function ( d, j ) {
                        //convert milliseconds to date
                        var date = new Date(d);
                        var options = { month: 'long', year: 'numeric' };
                        var dateToString = date.toLocaleDateString("en-US", options);
    
                        
                        select.append( '<option value="'+dateToString+'">'+dateToString+'</option>' )
                    } );
                } );
        } )
    
  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    I attempted to do it in the following way, but the options are appearing on the wrong reports. The option list is constantly changing when I use the following approach. When navigating to another tab, the drop down filter will sometimes have the correct values, then will switch the values of the datatables.

    var table = $('#table').on('xhr.dt', function ( e, settings, json, xhr ) {
            var tableFilter = $('#table').DataTable()
            tableFilter.columns([3]).every( function () {
                var column = this;
                var select = $('<select class="drop-down-date-filter" data-uk-dropdown><option value="">Date</option></select>')
                    .appendTo( $(column.header()).empty() )
                    .on( 'change', function () {
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );
    
                        column
                            .search( val ? '^'+val+'$' : '', true, false )
                            .draw();
                    } );
                column.data().unique().sort().each( function ( d, j ) {
                    //convert milliseconds to date
                    var date = new Date(d);
                    var options = { month: 'long', year: 'numeric' };
                    var dateToString = date.toLocaleDateString("en-US", options);
    
                    //reformat date and fill options with new date
                    select.append( '<option value="'+dateToString+'">'+dateToString+'</option>' )
                } );
            } );
        } ).DataTable( {
            ajax: {
                url: '/docs/accounting',
                dataSrc: ''
            },
            info: false,
            order: [[ 2, "asc" ]],
            paging: false,
            scrollX: true,
            scrollY: 500,
            searching: true,
            scrollCollapse: true,
            columns: [
    
  • kthorngrenkthorngren Posts: 20,379Questions: 26Answers: 4,781
    edited July 2019

    When navigating to another tab

    Do you have multiple tables on the same page with the same id ($('#table').DataTable())?

    With your code snippet its hard to visualize what is happening. Please post a link to your page or a test case replicating the issue. This will allow us to offer suggestions.

    You could use console.log statements in the xhr event to maybe help troubleshoot what is happening. That is where I would start.

    Kevin

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    I have one table that uses table.url().ajax().load to load multiple datasets in one table.

    Here is my JS File:

    $(document).ready(function() {
        
        var table = $('#table').on('xhr.dt', function ( e, settings, json, xhr ) {
            var tableFilter = $('#table').DataTable()
            tableFilter.columns([3]).every( function () {
                var column = this;
                var select = $('<select class="drop-down-date-filter" data-uk-dropdown><option value="">Date</option></select>')
                    .appendTo( $(column.header()).empty() )
                    .on( 'change', function () {
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );
    
                        column
                            .search( val ? '^'+val+'$' : '', true, false )
                            .draw();
                    } );
    
                column.data().unique().sort().each( function ( d, j ) {
                    //convert milliseconds to date
                    var date = new Date(d);
                    var options = { month: 'long', year: 'numeric' };
                    var dateToString = date.toLocaleDateString("en-US", options);
    
                    //reformat date and fill options with new date
                    select.append( '<option value="'+dateToString+'">'+dateToString+'</option>' )
                } );
            } );
        } ).DataTable( {
            ajax: {
                url: '/docs/accounting',
                dataSrc: ''
            },
            info: false,
            order: [[ 2, "asc" ]],
            paging: false,
            scrollX: true,
            scrollY: 500,
            searching: true,
            scrollCollapse: true,
            columns: [
                {
                    'targets': 0,
                    'searchable':false,
                    'orderable':false,
                    'className': 'dt-body-center',
                    'render': function (data, type, full, meta){
                        return '<input class="select" name="selection" type="checkbox">';
                    },
                    width: "5%"
                },
                {
                    data: "id",
                    width: "15%"
                },
                {
                    data: "department",
                    width: "25%"
                },
                {
                    data: "date",
                    //convert time from milliseconds to date
                    render: function(jsonDate) {
                        //convert numeric month into string
                        var date = new Date(jsonDate);
                        var options = { month: 'long', year: 'numeric' };
                        var dateToString = date.toLocaleDateString("en-US", options);
                        return dateToString;
                    },
                    orderable: false,
                    width: "15%"
                },
                {
                    data: "file",
                    render: function( data ) {
                        var message = "No file";
                        return message
                    },
                    sortable: false,
                    searchable: false,
                    class: "dt-body-center",
                    width: "15%"
                }
            ],
    
    
            initComplete: function () {
                //Drop down filter replaces the header title for Date
                this.api().columns([3]).every( function () {
                    var column = this;
                    var select = $('<select class="date-filter"><option value="">Date</option></select>')
                        .appendTo( $(column.header()).empty() )
                        .on( 'change', function () {
                            var val = $.fn.dataTable.util.escapeRegex(
                                $(this).val()
                            );
    
                            column
                                .search( val ? '^'+val+'$' : '', true, false )
                                .draw();
                    } );
                    
                    column.data().unique().sort().each( function ( d, j ) {
                        //convert milliseconds to date
                        var date = new Date(d);
                        var options = { month: 'long', year: 'numeric' };
                        var dateToString = date.toLocaleDateString("en-US", options);
    
                        //reformat date and fill options with new date
                        select.append( '<option value="'+dateToString+'">'+dateToString+'</option>' )
                    } );
                } );
            }
        
        } );
    
        $("#finance").click(function() {
            table.ajax.url('/docs/finance').load();
        });
    
        $("#accounting").click(function() {
            table.ajax.url('/docs/accounting').load();
        });
    
        $("#sales").click(function() {
            table.ajax.url('/docs/sales').load();
        });
        
    } );
    

    Here is my HTML for the datatable itself

    <div id="main-div" class="display" cellspacing="0" width="100%">
        <table id="table" class="display datatable" cellspacing="0" width="100%">
            <thead>
                <tr style="text-align: left">
                    <th><input name="select-all" value="1" class="select-all" type="checkbox" /></th>
                    <th>ID</th>
                    <th>Department</th>
                    <th>Date</th>
                    <th style="text-align: left;">File</th>
                </tr>
            </thead>
        </table>
    </div>
    

    this is my Navigation Menu JS file to change data

    function department(evt, departmentName) {
        var i, x, tablinks;
            x = document.getElementsByClassName("main-div");
        for (i = 0; i < x.length; i++) {
            x[i].style.display = "none";
        }
        tablinks = document.getElementsByClassName("tablink");
        for (i = 0; i < x.length; i++) {
            tablinks[i].className = tablinks[i].className.replace(" highlighted-department", "");
        }
        document.getElementById(departmentName).style.display = "block";
    }
    

    Finally, here is my html for the nav

    <ul class="nav" id="navigation">
        <li class="deparment-list">
            <a class="tablink" id="accounting">Accounting</a>
        </li>
        <li class="deparment-list">
            <a class="tablink" id="finance">Finance</a>
        </li>
        <li class="deparment-list">
            <a class="tablink" id="sales">Sales</a>
        </li>
    </ul>
    
  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    When I click on a navigation menu item, and then use the drop down filter on the date, the option values do not match up with the loaded dataset. For example:

    On the initial Load, the datatables defaults to the Accounting page. There is no problem with the drop down filter. When I navigate to Finance or Sales and then use the drop down filter, the option values are randomized from the other departments. Finance will show Sales, Sales will show Finance. When I go back to Accounting, the same thing happens.

    The problem is the randomization of my options within my dropdown filter. The option values show, just not on the right departments.

  • kthorngrenkthorngren Posts: 20,379Questions: 26Answers: 4,781

    Thats a lot of code to look through to try understanding the problem. If you can't provide a test case then I would start with some debugging (console.log) statments in the xhr event to help narrow down the issue.

    It could be a timing issue with the xhr event where the previous data is in the Datatables cache when the xhr event executes. Hard to say without actually seeing it. It could be that you need to loop through the json parameter data for the options instead of the column data.

    Kevin

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    How can I provide a test case? I ran console.log(xhr) and data gets returned back is:

    xhr return: [object Object]

    I'm sorry I'm not very good with jQuery and not familiar with testing it. What are some suggested statements to test in the xhr?

  • allanallan Posts: 61,864Questions: 1Answers: 10,136 Site admin

    Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.

    Allan

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2
    Answer ✓

    I was able to fix the problem by passing a function through load and then calling my drop down function.

    Instead of doing this:

    $("#finance").click(function() {
        table.ajax.url('/docs/finance').load();
    });
    

    I did this:

    $("#finance").click(function() {
        table.ajax.url('/docs/finance').load(
                function(){
                    table.columns([3]).every( function () {
                var column = this;
                var select = $('<select class="drop-down-date-filter" data-uk-dropdown><option value="">Date</option></select>')
                    .appendTo( $(column.header()).empty() )
                    .on( 'change', function () {
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );
    
                        column
                            .search( val ? '^'+val+'$' : '', true, false )
                            .draw();
                    } );
    
                column.data().unique().sort().each( function ( d, j ) {
                    //convert milliseconds to date
                    var date = new Date(d);
                    var options = { month: 'long', year: 'numeric' };
                    var dateToString = date.toLocaleDateString("en-US", options);
    
                    //reformat date and fill options with new date
                    select.append( '<option value="'+dateToString+'">'+dateToString+'</option>' )
                } );
            } );
                }
            );
    });
    
  • kthorngrenkthorngren Posts: 20,379Questions: 26Answers: 4,781

    Good find! Forgot about the callback option of ajax.url().load().

    Kevin

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    I have a question regarding the init function and my data point column. If I set searchable to false, the drop down does not work. The options get populated, but when you click on the option, there are "No results". How can I turn off the search, but keep the drop down column filter working

  • allanallan Posts: 61,864Questions: 1Answers: 10,136 Site admin

    As in you don't want DataTables' global search input? Remove the f option from dom (or if you don't have dom in use, define one without the f option).

    Allan

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    I do want the global search input, but I want to set a columns searchable to false. The only problem I have with that is, if I set it to false, the drop down filter I created does not work. The drop down filter will display the <option>'s, but when you click on an option with searchable set to false, No results get returned.

    When excluding the f option from the dom, it removes the search completely. I don't want it completely removed.

  • allanallan Posts: 61,864Questions: 1Answers: 10,136 Site admin

    Yes, if you mark a column as not searchable, then searching won't work on it.

    I feel I'm missing something here. Why are you creating select inputs for a column you don't want a search input on?

    Allan

  • markMathews1989markMathews1989 Posts: 43Questions: 7Answers: 2

    This is just one of the requirements we were given when displaying the data.

    We want to turn global search off on a column and replace it with a drop down. Everything works fine, just unable to disable the global search

  • kthorngrenkthorngren Posts: 20,379Questions: 26Answers: 4,781

    We want to turn global search off on a column and replace it with a drop down.

    You might be able to use a search plugin for this using the rowData parameter. Also use columns.searchable to disable global searching of the column. I modified one of my examples to illustrate this:
    http://live.datatables.net/tasohumi/1/edit

    The example is not exactly what you want with a drop down and it removes the selections instead of displaying them (reverse the return true and return false). But it should illustrate what to do.

    Note the use of draw() instead of search() in the change event. This will run the plugin without performing a search. Seems to work with a global search in place also. You will need to test to verify.

    HTH,
    Kevin

This discussion has been closed.