action callbacks inside collection buttons not triggered and enabled: false ignored on nested button

action callbacks inside collection buttons not triggered and enabled: false ignored on nested button

bolkanbolkan Posts: 6Questions: 1Answers: 0

Hi,

I’m using DataTables v2 with the new layout.buttons configuration. I have a collection button with child buttons inside it. The problem is twofold:

The child buttons inside the collection render correctly in the dropdown, but clicking them does not trigger their action callbacks at all.

Setting enabled: false on these nested child buttons does not disable them on initialization as expected; they appear enabled.

Here is a minimal example showing the issue:

https://jsfiddle.net/24s0dvrz/

Questions:
Is this a bug or known limitation of DataTables v2 when using layout.buttons with collection buttons?

Should the action callbacks work on nested buttons as usual?

Should enabled: false disable nested buttons on initialization?

Thanks in advance for any clarification.

Answers

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112
    edited July 28

    The action isn't being called because the collection buttons never become enabled. The button-selector you are using, ie actionsCollection.withdrawBtn:name, is not correct and won't select any button to enable/disable. You only need to provide the specific buttons name, for example withdrawBtn:name. Use this instead:

    table.button('withdrawBtn:name').enable(true);
    

    Updated test case:
    https://jsfiddle.net/47v1gywL/2/

    I added the datatables.css and buttons.css to show the styling of the buttons to see if they are enabled.

    Kevin

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112
    edited July 28

    Setting enabled: false on these nested child buttons does not disable them on initialization as expected; they appear enabled.

    You have enable: false, on the top level button but it should be

    I commented out these lines so you can see the buttons.buttons.enabled does work on the collection buttons:

      // table.button('actionsCollection:name').enable(false);
      // table.button('withdrawBtn:name').enable(false);
      // table.button('writeoffBtn:name').enable(false);
    

    https://jsfiddle.net/wrstL0e9/

    Click Actions without selecting a row to see the disabled collection buttons.

    Kevin

  • bolkanbolkan Posts: 6Questions: 1Answers: 0

    Makes perfect sense. Maybe i have some problems with loading datatables.

    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.0/css/bootstrap.min.css" rel="stylesheet" asp-append-version="true">
    <link href="https://cdn.datatables.net/v/bs5/jq-3.7.0/jszip-3.10.1/dt-2.3.2/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/date-1.5.6/r-3.0.5/rg-1.5.2/rr-1.5.0/sc-2.4.3/sl-3.0.1/sr-1.4.1/datatables.min.css" rel="stylesheet" integrity="sha384-qE0110NQMqud/TcrqtI6RPeJtWDuluLOKt7gxv7Q8RVkHOznCplyEj5NgDJr++ou" crossorigin="anonymous">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js" integrity="sha384-VFQrHzqBh5qiJIU0uGU5CIW3+OWpdGGJM9LBnGbuIH2mkICcFZ7lPd/AAtI7SNf7" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js" integrity="sha384-/RlQG9uf0M2vcTw3CX7fbqgbj/h8wKxw7C3zu9/GxcBPRKOEcESxaxufwRXqzq6n" crossorigin="anonymous"></script>
    <script src="https://cdn.datatables.net/v/bs5/jq-3.7.0/jszip-3.10.1/dt-2.3.2/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/date-1.5.6/r-3.0.5/rg-1.5.2/rr-1.5.0/sc-2.4.3/sl-3.0.1/sr-1.4.1/datatables.min.js" integrity="sha384-ZCYwIl/ImmUya/McxBODB3pwx8bVyUpgF4DtAo83o6BeR/WKwY5b7xHzLIStFSYG" crossorigin="anonymous"></script>
    
  • allanallan Posts: 64,838Questions: 1Answers: 10,731 Site admin

    You probably will have done yesterday, but things should be back to normal now. Does the CDN link you are using load okay for you? It is loading here, but there are some reports of caching errors that are taking a little while to clear.

    Allan

  • bolkanbolkan Posts: 6Questions: 1Answers: 0

    everything is loading correctly. Maybe the problem have something to do with loading data from ajax call

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112

    What exactly is the problem?

    What troubleshooting steps have you taken?

    Can you post a link to your page so we can help debug?

    Kevin

  • bolkanbolkan Posts: 6Questions: 1Answers: 0

    On a test scenario where i bind the table from html it works. But when i use serverSide with ajax the same setup does not work. I tried to call collectionRebuild on initComplete and add all buttons then but still not luck with action fire.

  • bolkanbolkan Posts: 6Questions: 1Answers: 0

    Here is my code
    $(function () {
    bindInvoicesTable();
    })

    function bindInvoiceButtons() {
        var invoiceButtons = [];
    
        invoiceButtons.push({
            text: '<i class="fa fa-plus"></i> ' + getTerm('Add from specification'),
            className: 'btn btn-primary btn-sm m-1',
            name: 'addFromSpec',
            action: function (e, dt, node, config, cb) {
                newInvoice(null, afterNewInvoiceFromSpecification, false);
            }
        });
    
        invoiceButtons.push({
            text: '<i class="fa fa-file-word"></i> ' + getTerm('Word Preview'),
            className: 'btn btn-primary btn-sm m-1',
            name: 'preview',
            enabled: false,
            action: function (e, dt, node, config, cb) {
                previewInvoice();
            }
        });
    
        //invoiceButtons.push({
        //  text: getTerm('Reissue'),
        //  className: 'btn btn-primary btn-sm m-1',
        //  name: 'reissue',
        //  action: function (e, dt, node, config, cb) {
        //      reissueInvoice();
        //  },
        //  enabled: false,
        //});
        //invoiceButtons.push({
        //  text: getTerm('Withdraw'),
        //  className: 'btn btn-primary btn-sm m-1',
        //  name: 'withdraw',
        //  action: function (e, dt, node, config, cb) {
        //      withdrawInvoice();
        //  },
        //  enabled: false,
        //});
    
        //invoiceButtons.push({
        //  text: getTerm('Write-off'),
        //  className: 'btn btn-primary btn-sm m-1',
        //  name: 'writeoff',
        //  action: function (e, dt, node, config, cb) {
        //      writtenoffInvoice();
        //  },
        //  enabled: false,
        //});
        //invoiceButtons.push({
        //  text: getTerm('Disputed-by-Client'),
        //  className: 'btn btn-primary btn-sm m-1',
        //  name: 'disputed',
        //  action: function () {
        //      disputedByClientInvoice();
        //  },
        //  enabled: false,
        //});
        //invoiceButtons.push({
        //  text: getTerm('In-Collection-Proceedings'),
        //  className: 'btn btn-primary btn-sm m-1',
        //  name: 'collectionProceedings',
        //  action: function (e, dt, node, config, cb) {
        //      inCollectionProceedingsInvoice();
        //  },
        //  enabled: false,
        //});
        invoiceButtons.push({
            extend: 'collection',
            className: 'btn btn-primary btn-sm m-1',
            text: 'Actions',
            name: 'actionsCollection',
            autoClose: true,
            buttons: [
                {
                    text: getTerm('Reissue'),
                    className: 'btn btn-primary btn-sm m-1',
                    name: 'reissue',
                    action: function (e, dt, node, config, cb) {
                        reissueInvoice();
                    },
                    enabled: false,
                },
                {
                    text: getTerm('Withdraw'),
                    className: 'btn btn-primary btn-sm m-1',
                    name: 'withdraw',
                    action: function (e, dt, node, config, cb) {
                        withdrawInvoice();
                    },
                    enabled: false,
                },
                {
                    text: getTerm('Write-off'),
                    className: 'btn btn-primary btn-sm m-1',
                    name: 'writeoff',
                    action: function (e, dt, node, config, cb) {
                        writtenoffInvoice();
                    },
                    enabled: false,
                },
                {
                    text: getTerm('Disputed-by-Client'),
                    className: 'btn btn-primary btn-sm m-1',
                    name: 'disputed',
                    action: function () {
                        disputedByClientInvoice();
                    },
                    enabled: false,
                },
                {
                    text: getTerm('In-Collection-Proceedings'),
                    className: 'btn btn-primary btn-sm m-1',
                    name: 'collectionProceedings',
                    action: function (e, dt, node, config, cb) {
                        inCollectionProceedingsInvoice();
                    },
                    enabled: false,
                }
            ]
        });
    
        invoiceButtons.push({
            text: '<i class="fa fa-money-bill"></i> ' + getTerm('Payments'),
            className: 'btn btn-primary btn-sm m-1',
            name: 'payments',
            enabled: false,
            action: function (e, dt, node, config, cb) {
                showInvoicePayment();
            }
        });
    
        invoiceButtons.push({
            text: '<i class="fa fa-arrows-down-to-people"></i> ' + getTerm('Allocations'),
            className: 'btn btn-primary btn-sm m-1',
            name: 'allocations',
            enabled: false,
            action: function () {
                showInvoiceLawyerAllocations();
            }
        });
    
        return invoiceButtons;
    }
    
    $('#invoicesTable tbody').on('click', 'tr', function () {
        if ($(this).hasClass('selected')) {
            $(this).removeClass('selected');
            selectedInvoice = null;
        } else {
            invoicesTable.$('tr.selected').removeClass('selected');
            $(this).addClass('selected');
        }
        selectedInvoice = invoicesTable.row('.selected').data();
    
        if (selectedInvoice) {      
            invoicesTable.button('preview:name').enable(true);
            invoicesTable.button('actionsCollection:name').enable(true);
            invoicesTable.button('reissue:name').enable(true);
            invoicesTable.button('withdraw:name').enable(true);
            invoicesTable.button('writeoff:name').enable(true);
            invoicesTable.button('disputed:name').enable(true);
            invoicesTable.button('collectionProceedings:name').enable(true);
            invoicesTable.button('payments:name').enable(true);
    
            $('#cmbExportLanguage').val(selectedInvoice.client.language.code);
        } else {        
            invoicesTable.button('preview:name').enable(false);
            invoicesTable.button('actionsCollection:name').enable(false);
            invoicesTable.button('reissue:name').enable(false);
            invoicesTable.button('withdraw:name').enable(false);
            invoicesTable.button('writeoff:name').enable(false);
            invoicesTable.button('disputed:name').enable(false);
            invoicesTable.button('collectionProceedings:name').enable(false);
            invoicesTable.button('payments:name').enable(false);        
        }
    });
    
    function bindInvoicesTable() {
        invoicesTable = bindEntitiesTable('invoicesTable', 'get-invoices-paged');
    }
    
    function bindEntitiesTable(elementId, ajaxUrl) {
        DataTable.feature.register('languageSelector', function (settings, opts) {
            let toolbar = document.createElement('div');
            toolbar.className = "input-group";
            var options = '<label class="active p-1 text-white">' + getTerm("Export language") + '</label><select class="form-control form-control-sm" id="cmbExportLanguage">';
            $.each(languages, function (i, item) {
                var selected = "";
                if (item.code == locale)
                    selected = "selected";
                options += "<option " + selected + " value='" + item.code + "'>" + item.description + "</option>"
    
            });
            options += '</select>';
            toolbar.innerHTML = options;
            return toolbar;
        });
        var table = $('#' + elementId).DataTable({
            serverSide: true,
            ajax: {
                url: '/' + locale + '/Billing/' + ajaxUrl,
                type: 'POST',
            },      
            layout: {
                topStart: {
                    buttons: elementId == 'fiscalReceiptsTable' ? bindFiscalReceiptButtons() :bindInvoiceButtons()
                },
                topEnd: {
                    languageSelector: {
    
                    },
                    search: {
                        text: '',
                        placeholder: getTerm('Search')
                    }
                },
                bottomStart: ['pageLength', 'info'],
                bottomEnd: 'paging'
            },
            language: dataTableLanguage,
            destroy: true,
            info: true,
            paging: true,
            displayLength: 25,
            lengthMenu: [10, 25, 50, 100],
            searching: true,
            ordering: false,
            scrollY: '41.3rem',
            scrollX: true,
            scroller: false,
            rowId: function (a) {
                return '#rowId-' + a.invoiceId;
            },
            initComplete: function () {
                $(this.api().table().container()).find('input').attr('autocomplete', 'off');
            },
            columns: [
                //my columns here
            ]
        });
    
        return table;
    }
    

    When I comment adding of button (actionsCollection) and comment out the commented code it works

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112

    I don't see anything obvious. That's a lot of code to try debugging just by looking at it. We will need a test case to trace through the code. If you can't post a link to your page or send the link privately to Allan then please build a test case the replicates the issue. You can get a server side processing template to start with here.

    Kevin

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112

    I had a few minutes so I built a test case with your above code:
    https://live.datatables.net/yaroyala/122/edit

    Made some modifications for it to work in the JS Bin environment. I added select: true to get the selected class. Not sure if you are using this but it wasn't in your code. Commented out the language stuff as it doesn't pertain to the issue.

    The first thing I noticed is the click event wasn't firing. In my test case the HTML table is defined like this:

          <table id="example" class="display" width="100%">
            <thead>
              <tr>
                <th>Name</th>
                <th>Position</th>
                <th>Office</th>
                <th>Extn.</th>
                <th>Start date</th>
                <th>Salary</th>
              </tr>
            </thead>
    
            <tfoot>
              <tr>
                <th>Name</th>
                <th>Position</th>
                <th>Office</th>
                <th>Extn.</th>
                <th>Start date</th>
                <th>Salary</th>
              </tr>
            </tfoot>
          </table>
    

    Notice no tbody so the click event selector of $('#invoicesTable tbody').on('click', 'tr' won't work since the tbody doesn't exist in the document when the click event is instantiated. I changed the selector to this:

    $('#invoicesTable').on('click', 'tbody tr', function () {
    

    Now the click event fires and the code to enable/disable the buttons now works. I suggest doing some debugging to see if the click event is working in your environment. If not make the same change I made. Is this your issue?

    If this doesn't solve the issue then please update my test case to show the problem.

    Kevin

  • bolkanbolkan Posts: 6Questions: 1Answers: 0

    My table is defined like this

    <table id="invoicesTable" class="table table-striped table-bordered w-100 p-0">
        <thead class="table-dark"></thead>
        <tbody></tbody>
    </table>
    

    The event you mentioned is trigger each time i click on a row. Still buttons in the collection do not fire the action. I am starting to think that this have something with bootstrap 5 styling of the table.

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112

    I am starting to think that this have something with bootstrap 5 styling of the table.

    I removed the select extension and used the Download Builder to create a Bootstrap 5 environment. I changed the click event selector back to what you have and added the tbody tag.

    https://live.datatables.net/yaroyala/124/edit

    The code still seems to work correctly. Clicking the row enables the collection buttons.

    Did you include the Datatables Bootstrap integration files for the version you are using? Use the Download Builder for this.

    Have you stepped through the event handler code to make sure it's doing what you expect?

    I think to further troubleshoot we will need to see a link to your page or test case that replicates the issue.

    Kevin

  • kthorngrenkthorngren Posts: 22,214Questions: 26Answers: 5,112
    edited July 31

    Is the problem that the buttons aren't being enabled or that the action function isn't executing or executing as expected. If the latter check the console for errors when clicking the button.

    Kevin

Sign In or Register to comment.