Run code after draw

Run code after draw

SamerJ92SamerJ92 Posts: 4Questions: 2Answers: 0

I use server side tables on my site, and to be able to properly export all rows to Excel, I have to change the page length to "-1", which loads all the rows and run "draw()" before manually running the export command. I set a timeout of 8000ms to allow it time to draw the table first before exporting.

This is the Excel button code that does this:

$.fn.dataTable.ext.buttons.excelAll = {
    text: 'Excel',
    action: function ( e, dt, node, config ) {
        dt.page.len(-1).draw()
        setTimeout(() => { 
            $.fn.dataTable.ext.buttons.excelHtml5.action.call(this, e, dt, node, config)
            dt.page.len(10).draw()
        }, 8000)
    }
}

This works absolutely fine, until I'm working with a table with over 10,000 rows. The timeout is not long enough.

I could just increase the timeout, but I'd like to think there is probably a more elegant way of doing this. Is there a way I can wait for it to finish drawing the table? I could add a listener for the draw event but that would trigger on every single draw when I only want to do it when the Excel button is pressed.

Any help would be greatly appreciated. Thanks!

Answers

  • colincolin Posts: 15,237Questions: 1Answers: 2,599

    You could do that trigger on draw as you said, and use a global variable to determine if this is part of an export. You could also use the xhr - as this triggers when the ajax is complete.

    The problem with your implementation is that the table would draw twice, and the users positioning would be lost. A better solution perhaps would be to customise the exportOptions to tell the export to get the data from the server, while leaving the table intact - this thread has a good discussion on that.

    Colin

  • SamerJ92SamerJ92 Posts: 4Questions: 2Answers: 0

    @colin

    So I'm now triggering the button on the draw event like so:

    this.dt.on('draw', function () {
                    if (vm.excel == true)
                    {
                        vm.excel = false
                        $.fn.dataTable.ext.buttons.excelHtml5.action.call(vm.excelOptions.button, vm.excelOptions.e, vm.excelOptions.dt, vm.excelOptions.node, vm.excelOptions.config)
                        vm.loader.hide()
                        vm.dt.page.len(vm.user.page_length).draw()
                    }
                })
    

    Updated button code:

    $.fn.dataTable.ext.buttons.excelAll = {
                    text: 'Excel',
                    filename: 'ProjectNav Data',
                    header: true,
                    action: function (e, dt, node, config) {
                        vm.loader = vm.$loading.show({
                            container: vm.$refs.table
                        })
                        vm.excel = true
                        vm.excelOptions = {
                            button: this,
                            e: e,
                            dt: dt,
                            node: node,
                            config: config
                        }
                        dt.page.len(-1).draw()
                    }
                }
    

    It all works good, except it doesn't redraw the table properly. I set it to change the length of the table back to the user's setting (in this case, 10). It changes the pagination from no pages to 8, but still shows all the rows rather than 10 per page. Is there something I'm doing wrong here or do I need to force the table to redraw somehow?

  • colincolin Posts: 15,237Questions: 1Answers: 2,599

    We're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. 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.

    Cheers,

    Colin

This discussion has been closed.