How can close child rows on change page?

How can close child rows on change page?

david.papinidavid.papini Posts: 21Questions: 5Answers: 0
edited February 2020 in Free community support

Hi i've a child rows from ajax call. I need to close all child opened when user change page.
How can do it?

Thank you

Answers

  • colincolin Posts: 15,112Questions: 1Answers: 2,583

    This example from this thread shows how you can close them all - it only allows one open. You could do the same in a draw or page,

    Colin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    Thank you 4 your answer, but i need to close opened child on change page, but i can't use draw and i don't trigger when click on number page.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    The simplest case is to use rows().every() to loop all the rows. You can then use row().child.isShown() to detemine if the child is shown and if so then either row().child.hide() or row().child.remove(). You can do things to be more efficient if you have lots of rows. If you need help with this part then post more information about what you have and want.

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    ok, it'a a possibility.
    where i can use row().every() on 'draw' event?

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited February 2020

    Yes. If you do that then use selector-modifier of {page:'current'} to just iterate the visible rows.

    EDIT: Just notice Colin's reply. At least we gave consistent answers :wink:

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    this is my code

            $('#tablePianodicaricoMaster').on('draw.dt', function () {
                lastPage = $('#tablePianodicaricoMaster').DataTable().page();
    
                var table = $('#tablePianodicaricoMaster').DataTable();
    
                table.rows({ page: 'current' }).every(function () {
                    var row = this;
                    if (row.child.isShown()) {
                        var tr = $(table).closest('tr');
                        tr.removeClass('details');
                        row.child.hide();
    
                        // Remove from the 'open' array
                        detailRows.splice(row.index, 1);
                    }
                }); 
            });
    

    the issue is that when i expand child row, by button, i close it on same time...

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    the issue is that when i expand child row, by button, i close it on same time

    I put your code in this test case and it doesn't exhibit that problem.

    However there are a couple other issues. tr.removeClass('details'); is probably not changing the row details button. The class should be shown and $(table).closest('tr'); wasn't giving the expected row in the test case. I updated the code based on Colin's example. Also commented out detailRows.splice(row.index, 1); as I don't have that array defined.

    Please update the test case to replicate the problem.

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0
    edited February 2020

    Thank you, i can't update you test, but i think tha my issue is on mode to load data into table

    $.ajax({
        type: t,
        data: { "StringSearch": JSON.stringify($("#" + id).serializeObject()) },
        beforeSend: function () { $('.caption > span.caption-subject > .fa-spinner').show()},
        url: WcfPath + AjaxFunction,
        contentType: "application/json; charset=utf-8",
        dataType: d,
    }).done(function (result) {
        $(idTable).DataTable().clear().draw();
        $(idTable).DataTable().rows.add($.parseJSON(result.Data)).draw();
    
        if (lastPage != null && lastPage != undefined) {
            $(idTable).DataTable().page(lastPage).draw('page');
        }                          
    
        if ($.isArray(detailRows)) {
            //Riapre le child aperte prima del salvataggio
            var api = new $.fn.dataTable.Api($(idTable).DataTable().settings());
            for (var i = 0; i < detailRows.length; i++) {
                api.$('tr')
                    .eq(detailRows[i])
                    .find('td.details-control')
                    .each(function () {
                        onRowDetailsClick.call(this, api);
                    });
            }
        }
    
        $(idResult).show();
        $('.caption > span.caption-subject > .fa-spinner').hide();
    }).fail(function (jqXHR, textStatus, errorThrown) {
        alert("errore:" + textStatus);
    });
    

    So when i trigger 'draw' i close on my hand the child that i 've opened

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    Just to make sure I understand the problem. When you click the plus sign button the child opens then closes. Is this correct?

    I'm not sure how the above code would cause that as the draw() APIs are called after you load the table data but before you reopen the child rows.

    If you are unable to show use the problem then I would start by adding a console.log statement to your click event to open the rows. Does it execute more than once when clicking the button? Are you calling draw() in the event?

    Just as an FYI... Here is an alternative way to reopen the child rows after reloading the table which eliminates the need to call something to click the button:
    http://live.datatables.net/qolevune/1/edit

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0
    edited February 2020

    yes you have get me.
    the api is called after load data to reposition on last page and reopen the child before the update.

    very update data i reload, by ajax, the full datatable.

    this is the code to load chid

    function onRowDetailsClick(table) {
                var tr = $(this).closest('tr');
                var row = $('#tablePianodicaricoMaster').DataTable().row(tr);
                var rowData = row.data();
                var idx = $.inArray(row.index(), detailRows);
                var _url = App.getGlobalWcfErgonPath() + "GetDtPianoDiCaricoDetail";
                var _data = JSON.stringify({ pCdDeposito: $("#pCdDeposito").val(), pDtConsegna: moment($('#pDtConsegna').closest('div.date-picker').datepicker('getDate')).format(), pCdGiro: rowData.CdGiro });
    
                if (row.child.isShown()) {
                    tr.removeClass('shown');
                    row.child.hide();
    
                    // Remove from the 'open' array
                    detailRows.splice(row.index(), 1);
                }
                else {
                    tr.addClass('shown');
                    //row.child(format(row.data())).show();
                    row.child("<div class='wrapper loading'><div id='loadDetail" + rowData.CdGiro + "' class='elaborazione'>Elaborazione ...</div>" +
                        "<table class='table table-bordered table-hover child_table' cellspacing='0'  id='tablePianodicaricoDetail" + rowData.CdGiro +
                        "' style='padding-left:50px;'><tbody></tbody></table></div>").show();
    
                    var detailsTableOpt = $('#tablePianodicaricoDetail' + rowData.CdGiro).dataTable({
                        'dom': 'Bfrtip',
                        'data': [],
                        'serverSide': false,
                        'processing': false,
                        'scrollY': '50vh',
                        'scrollCollapse': true,
                        'searching': false,
                        'info': false,
                        'paging': false,
                        'language': { "url": "//cdn.datatables.net/plug-ins/1.10.16/i18n/Italian.json" },
                        'destroy': true,
                        'responsive': true,
                        'order': [],
                        
                        'columns': [
                            { data: null, className: "dt-body-center", render: function (data, type, full) { return jsFunctionCheckBox(data, type, full); }, orderable: false },
                            { data: "Sequenza", title: "Seq.", className: "dt-center details-control1", visible: true, orderable: true },
                            { data: "CdCli", title: "Cliente", className: "dt-center", visible: true, orderable: false },
                            { data: "RagioneSociale", title: "Ragione Sociale", className: "dt-left", visible: true, orderable: false, render: function (data, type, full) { return jsFunctionRagioneSociale(data, type, full); } },
                            { data: "Indirizzo", title: "Indirizzo", className: "dt-left", visible: false, orderable: false },
                            { data: "Localita", title: "Località", className: "dt-left", visible: true, orderable: false },
                            { data: "Provincia", title: "Provincia", className: "dt-left", visible: false, orderable: false },
                            { data: "NrRighe", title: "Nr. Righe", className: "dt-right", visible: true, orderable: false },
                            { data: "Bloccato", title: "Bloccato", className: "dt-right", visible: false, orderable: false },
                            { data: "StatoOrdine", title: "StatoOrdine", className: "dt-right", visible: false, orderable: false },
                            { data: "GV", title: "GV", className: "dt-right", visible: true, orderable: false, render: function (data, type, full, meta) { return jsFunctionHideZeroD(data, type, full, meta); } },
                            { data: "OF", title: "OF", className: "dt-right", visible: true, orderable: false, render: function (data, type, full, meta) { return jsFunctionHideZeroD(data, type, full, meta); } },
                            { data: "SG", title: "SG", className: "dt-right", visible: true, orderable: false, render: function (data, type, full, meta) { return jsFunctionHideZeroD(data, type, full, meta); } },
                            { data: "PF", title: "PF", className: "dt-right", visible: true, orderable: false, render: function (data, type, full, meta) { return jsFunctionHideZeroD(data, type, full, meta); } },
                            { data: "CR", title: "CR", className: "dt-right", visible: true, orderable: false, render: function (data, type, full, meta) { return jsFunctionHideZeroD(data, type, full, meta); } },
                            { data: "SL", title: "SL", className: "dt-right", visible: true, orderable: false, render: function (data, type, full, meta) { return jsFunctionHideZeroD(data, type, full, meta); } },
                            { data: "TotaleKg", title: "Tot. KG.", className: "dt-right", visible: true, orderable: false },
                            { data: "Im", title: "Importo", className: "dt-right", visible: false, orderable: false },
                            { data: "NoteOrdine", title: "Note", className: "dt-right", visible: false, orderable: false },
                            { data: null, title: "Azioni", className: "dt-right", visible: true, orderable: false, render: function (data, type, full) { return jsFunctionAction(data, type, full); } },
                            { data: "AnnoOrdine", title: "AnnoOrdine", className: "dt-left", visible: false, orderable: false },
                            { data: "NrOrdine", title: "NrOrdine", className: "dt-left", visible: false, orderable: false },
                            { data: "CdGiro", title: "CdGiro", className: "dt-left", visible: false, orderable: false },
                            { data: "DsGiro", title: "DsGiro", className: "dt-left", visible: false, orderable: false },
                            { data: "DtConsegna", title: "DtConsegna", className: "dt-left", visible: false, orderable: false },
                        ],
                        'select': {
                            style: 'os',
                            selector: 'multi'
                        },
                    });
    
                    $.ajax({
                        type: "POST",
                        data: { "StringSearch": _data },
                        url: _url,
                        contentType: "application/json; charset=utf-8",
                        dataType: "jsonp",
                    }).done(function (result) {
                        $(detailsTableOpt).DataTable().clear().draw();
                        $(detailsTableOpt).DataTable().rows.add($.parseJSON(result.Data)).draw();
    
                        var inputCheckBox = document.createElement('input');
                        inputCheckBox.id = "detail-select-all";
                        inputCheckBox.type = "checkbox";
                        inputCheckBox.onclick = function () { return selezionaTutto(this, $(detailsTableOpt).attr('id')); }
                        $($(detailsTableOpt).DataTable().table().header()).find('th').eq(0).append(inputCheckBox);
    
                        setEditButton();
    
                        $('.wrapper').removeClass('loading');
                        $('#loadDetail' + rowData.CdGiro).hide();
                    }).fail(function (jqXHR, textStatus, errorThrown) {
                        alert("errore:" + textStatus);
                    });
    
                    // Add to the 'open' array
                    if (idx === -1) {
                        detailRows.push(row.index());
                    }
                }
    

    Edited by Kevin:  Syntax highlighting. Details on how to highlight code using markdown can be found in this guide

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    I'm still not seeing anything that would show why the $('#tablePianodicaricoMaster').on('draw.dt', function () event would cause the row you just clicked to show then hide. Is there another place in the code that might execute something to cause Datatables to draw, like calling a search, order or page API. Or maybe something that calls onRowDetailsClick()?

    I would use console log statements in each event to see when they are called. Maybe you will see one of them unexpectedly called when you open a child row.

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    i find it, i think.

    when i load the data child

                    $(detailsTableOpt).DataTable().rows.add($.parseJSON(result.Data)).draw();
    

    this code call me the draw.dt event of my master table

    how can i fix it?

  • colincolin Posts: 15,112Questions: 1Answers: 2,583

    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

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    You are using the draw() API with this $(detailsTableOpt).DataTable().... table. But your draw event, $('#tablePianodicaricoMaster').on('draw.dt', function () {, is applied to a different table. So, that draw() should not invoke this event.

    What happens if you comment out the statement row.child.hide(); in the event?

    $('#tablePianodicaricoMaster').on('draw.dt', function () {
        lastPage = $('#tablePianodicaricoMaster').DataTable().page();
     
        var table = $('#tablePianodicaricoMaster').DataTable();
     
        table.rows({ page: 'current' }).every(function () {
            var row = this;
            if (row.child.isShown()) {
                var tr = $(table).closest('tr');
                tr.removeClass('details');
                row.child.hide();
     
                // Remove from the 'open' array
                detailRows.splice(row.index, 1);
            }
        });
    });
    

    You have a lot going on and its difficult for us to peice together your code snippets. As Colin said can you post a link to your page so we can take a look.

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    DataTable > click td.details-control [Wed Feb 19 2020 14:44:29 GMT+0100 (Ora standard dell’Europa centrale)]
    PianoDiCarico:1450 DataTable > onRowDetailsClick [Wed Feb 19 2020 14:44:29 GMT+0100 (Ora standard dell’Europa centrale)]
    PianoDiCarico:1707 DataTable > draw.dt [Wed Feb 19 2020 14:44:29 GMT+0100 (Ora standard dell’Europa centrale)]
    PianoDiCarico:1708 console.trace

    this is my stack trace, last draw.dt is called from this row
    var detailsTableOpt = $('#tablePianodicaricoDetail' + rowData.CdGiro).dataTable({

    i can't public my page, because i put in fail my production.

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited February 2020

    Initializing a Datatable will call draw() but it will be for the table being initialized. The child detail table in your case. I suspect that PianoDiCarico:1707 DataTable > draw.dt is the drawing of the child table.

    You didn't answer my question. What happens if you comment out row.child.hide();?

    Seems like your full Datatables code might be long. Even if it doesn't run maybe you can post it in a test case. We can scan through to see if anything obvious stands out.
    https://datatables.net/manual/tech-notes/10#How-to-provide-a-test-case

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    if i comment out row.child.hide() child is opened

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited February 2020

    Sounds like something else on your page is causing the tablePianodicaricoMaster table to draw. I might be missing it but I don't see it in any of the above code. There is this code:

    }).done(function (result) {
        $(idTable).DataTable().clear().draw();
        $(idTable).DataTable().rows.add($.parseJSON(result.Data)).draw();
    

    But that seems independent of your onRowDetailsClick() function. Unless you can post your code so we can see it you will need to trace through it to find out why the tablePianodicaricoMaster table is redrawing when open a child row.

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0
    edited February 2020
  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    When you open the child row does it close right away or maybe after a short period of time?

    I see this that may draw the tablePianodicaricoMaster every 60 seconds.

                $('#flRefresh').on('change', function () {
                    var pages = $('#tablePianodicaricoMaster').DataTable().page.info().pages;
                    var page = $('#tablePianodicaricoMaster').DataTable().page();
                    if (this.checked) {
                        idInterval = setInterval(function () {
                            page++;
                            $('#tablePianodicaricoMaster').DataTable().page(page).draw('page');
                            if (page >= pages - 1) page = -1;
                        }, 60000);
                    }
                    else {
                        clearInterval(idInterval);
                    }
                });
    

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    yes but if only flrefresh is checked onpage

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736
    edited February 2020

    Interesting. I put your relevant code into a test case:
    http://live.datatables.net/marimelo/2/edit

    I updated the click event to this:

               $('#tablePianodicaricoMaster').on('draw.dt', function (e, settings) {
                    console.log('DataTable > draw.dt [' + new Date() + "]");
                    //console.trace();
                    console.log('Table ID: ', settings.nTable.id);
                    ......
    

    With $('#tablePianodicaricoMaster').on('draw.dt' the event executes even when the child Datatables draws, for example:

    DataTable > click td.details-control [Fri Feb 21 2020 11:59:11 GMT-0500 (Eastern Standard Time)]
    runner-3.17.11.min.js:1 DataTable > draw.dt [Fri Feb 21 2020 11:59:12 GMT-0500 (Eastern Standard Time)]
    runner-3.17.11.min.js:1 Table ID:  tablePianodicaricoDetailundefined
    

    Changing 'draw.dt' to 'draw' fixes the issue. Maybe @allan or @colin can explain why $('#tablePianodicaricoMaster').on('draw.dt' is invoked with the child Datatable.

    Working example with $('#tablePianodicaricoMaster').on('draw', function (e, settings) {:
    http://live.datatables.net/xanajisu/1/edit

    Kevin

  • kthorngrenkthorngren Posts: 20,142Questions: 26Answers: 4,736

    I looked at this further. You will need to use draw.dt as draw won't work for your particular solution. Since the child is a Datatable it's draw events bubble up to the parent Datatable. You will need to use Event.stopPropagation for your child Datatables, for example:

                    var detailsTableOpt = $('#tablePianodicaricoDetail' + rowData.CdGiro)
                      .on('draw.dt', function (e) {
                        e.stopPropagation();
                      })
                      .dataTable({ ... });
    

    Here is the updated example:
    http://live.datatables.net/xanajisu/3/edit

    Kevin

  • david.papinidavid.papini Posts: 21Questions: 5Answers: 0

    thank you, now it's working!

This discussion has been closed.