Parent / child editing with RowId on parent

Parent / child editing with RowId on parent

INRINR Posts: 20Questions: 2Answers: 1

I am following this article ( https://datatables.net/blog/2019-01-11 ) and it works.

But when RowId is specified for the parent table, the child will not be displayed. I am using RowId to enable the Line Edit option

Can you please provide a suggestion ?

Answers

  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin

    I'm afraid I don't quite understand what you are looking for.

    But when RowId is specified for the parent table, the child will not be displayed.

    Is that a customisation over what the blog post does? Or are you getting to a specific step in the blog which is failing for you?

    Can you link to a page showing the issue you are seeing please?

    Thanks,
    Allan

  • INRINR Posts: 20Questions: 2Answers: 1

    Hi Allan,,

    yes, I am trying to extend the functionality (in-line editing) of what is explained on the post.

    i am not using the C# Server-side editor components and passing the modified row (all columns) to C# via AJAX. I have to specify the RowId, to make it work.

    the below is the code (slightly different to https://datatables.net/blog/2019-01-11) the which i am working with. When RowId is commented, when clicking the expand image, the child will get open and it works. When RowId is uncommented, the child will open and automatically gets closed. I tested with same code as https://datatables.net/blog/2019-01-11 and the behavior is same.


        var table = $("#Table1").DataTable({
                async: true,
                serverSide: false, 
                deferRender: true, 
                deferLoading: 0, 
                orderMulti: true,
                select: {
                    style: 'single'
                },
                ajax: {
                    url: "/Home/Table1_Search",
                    type: "POST",
                    datatype: "json",
                    data: function (d) {
                        d.val1 = 1,
                        d.val2 = 2
                    }
                },
                orderClasses: false,
                order: [[1, 'asc']],
                columnDefs:[],
                columns: [
                    {
                        data: null, name: "Group", title: "", orderable: false, width: 20,
                        render: function (data, type, row, meta) {
                            return '<img id="detail-content" src="~/../../Images/Expand.png">';
                        }
                    },
                    { data: "HeaderId", name: "HeaderId", title: "#", width: 60 },
                    { data: "Group", name: "Group", title: "Group", orderable: false, width: 120 }
                ]
                //, rowId: 'HeaderId'
            });
    
        $('#Table1 tbody').on('click', 'td img', function () {
                var nTds = this;
                var nTr = $(this).parents('tr')[0];
                var row = $(this).closest('tr');
                var table = $('#Table1').dataTable();
                var headerId = table.fnGetData(row).HeaderId;
    
                var innerTable;
    
                if (table.fnIsOpen(nTr)) {
                    closeChildTable(this, nTr, table, "#Table1" + headerId) /* This row is already open - close it */
                }
                else
                {
                    this.src = "~/../../Images/Collapse.png";
                    var tabclass = headerId+'-detail';
                    table.fnOpen(nTr, fnFormatDetails(headerId, detailsTableHtml), tabclass); 
    
                    innerTable = $("#Table1_" + headerId).DataTable({
                        async: true,
                        serverSide: false, // for process server side
                        scrollX: false, //Enable Horizonal Scroll
                        deferRender: true, // deferred rendering
                        filter: true,
                        orderMulti: true,
                        info: false,
                        paging: false,
                        select: false,
                        ajax: {
                            url: "/Home/Table2_Search",
                            type: "POST",
                            datatype: "json",
                            data: function (d) {
                                d.headerId = headerId
                            }
                        },
                        orderClasses: false,
                        order: [[0, 'asc']],
                        columnDefs: [],
                        columns: [
                            { data: "LineNumber", name: "LineNumber", visible: false, autoWidth: true },
                            { data: "HeaderId", name: "HeaderId", visible: false, autoWidth: true },
                            { data: "ProductId", name: "ProductId", visible: false, autoWidth: true }
                        ]
                    });
                }
            });
    
        function fnFormatDetails(table_id, html) {
            var sOut = "<table id=\"Table1_" + table_id + "\" class=\"table table-striped table-bordered display compact hover stripe dataTable no-footer table-child\" style=\"width:100%!important\">";
            sOut += html;
            sOut += "</table>";
            return sOut;
        }
    
        function closeChildTable(nTd, nTr, table, name) {
            /* This row is already open - close it */
            nTd.src = "~/../../Images/Expand.png";
            table.fnClose(nTr);
    
            // Destroy the Child Datatable
            $(name).DataTable().destroy();
        }    
    

  • INRINR Posts: 20Questions: 2Answers: 1

    Hi Allan,

    the post works if we use as it is. When I add rowId to the parent table, it will the child table automatically gets closed when its opened.

    Looks like rowId is causing some issues and the child table gets automatically closed when it opens. If I comment the rowId, it works like how it explained on the post.

    hope this helps.

  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin

    It's not immediately obvious to me why rowId: 'HeaderId' would make any difference there. Can you give me a link to your page so I can trace it through please?

    Thanks,
    Allan

  • INRINR Posts: 20Questions: 2Answers: 1

    Hi Allan,

    HeaderId is the uniqueKey on the dataset. I am trying to use the in-line editing.

    you add any column as like rowId: 'xxx' and the Child dataTable will close automatically when its opened/expanded.

    Probably I will prepare a working script and provide.

  • INRINR Posts: 20Questions: 2Answers: 1

    Hi Allan,

    I think I found the combination of attributes which are causing this issue. The problem occurs when we specify "responsive: true" and "rowId: 'HeaderId' on the parent data table.

    but I couldn't re-produce with jsfiddle ( https://jsfiddle.net/INR_R/1pnz2wvk/45/ )

    Is it possible for you to gran the code from my jsfiddle and test in your environment with these 2 parameters enabled?

    Regards

  • INRINR Posts: 20Questions: 2Answers: 1

    we have to use AJAX data source to get the issue. thats why in jsfiddle i couldnt get the issue.

    I use ajax call to the C# method.

            ajax: {
                    url: "/Home/Table1_Search",
                    type: "POST",
                    datatype: "json",
                    data: function (d) {
                        d.option = 0
                    }
                },
    
  • INRINR Posts: 20Questions: 2Answers: 1
    edited January 2021
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.23/css/jquery.dataTables.css">
    <script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.23/js/jquery.dataTables.js"></script>
    
    <html>
    <div id="Wrapper1">
        <table id="Table1" class="table table-striped table-bordered display compact hover stripe dataTable no-footer" style="width:100%!important">
            <thead>
                <tr class="bir-selection-color1 text-center">
                    <th>Expand</th>
                    <th>Id</th>
                    <th>Group</th>
                </tr>
            </thead>
        </table>
    
        <div id="Wrapper2" style="display:none;">
            <table id="Table2" class="table table-striped table-bordered display compact hover stripe dataTable no-footer" style="padding-left: 15px!important">
                <thead>
                    <tr class="bir-selection-color1 text-center">
                        <th>Id</th>
                        <th>HeaderId</th>
                        <th>ProductId</th>
                    </tr>
                </thead>
            </table>
        </div>
    </div>
    </html>
    
    <script type="text/javascript">
        var dataSet1 = [{ "HeaderId": "1", "Group": "Group 1" }
                            ];
    
        var dataSet2 = [{ "LineNumber": "1", "HeaderId": "1", "ProductId": "1011" },
                        { "LineNumber": "2", "HeaderId": "1", "ProductId": "1012" }
                        ];
    
    
    //dataTables default values
    var dataTablesdefaultPageLength = 100;
    var dataTablesPageLengthDisplay = [50, 100, 250, 500];
    
    var dataTablesserverSide = false;
    var dataTablesautoWidth = true;
    var dataTablesresponsive = true;
    var dataTablesprocessing = true;        // for show progress bar 
    var dataTablesfilter = true;            // this is for disable filter (search box)
    var dataTablesorderMulti = false;       // for disable multiple column at once  
    
    var dataTablesscrollX = false;
    
        $(document).ready(function () {
    
            // Get the Detail Table as Template for Every Row
            detailsTableHtml = $("#Table2").html();
    
            var table1 = $("#Table1").DataTable({
                async: true,
                    serverSide: false, // for process server side
                    deferRender: true, // deferred rendering
                    scrollX: dataTablesscrollX,
                    deferLoading: 0, //Disable Initial Load
                    processing: dataTablesprocessing, // for show progress bar
                    filter: dataTablesfilter,
                    orderMulti: true,
                    autoWidth: dataTablesautoWidth,
                    responsive: dataTablesresponsive,
                    pageLength: dataTablesdefaultPageLength,
                    lengthMenu: [dataTablesPageLengthDisplay, dataTablesPageLengthDisplay],
                    data: dataSet1,
                    order: [[1, 'asc']],
                    columnDefs: [],
                    columns: [
                    {
                        data: null, name: "Group", title: "", className: 'details-control', orderable: false, width: 20,
                        render: function (data, type, row, meta) {
                            return '<img id="detail-content" src="~/../../Images/Expand.png">';
                        }
                    },
                    { data: "HeaderId", name: "HeaderId", title: "#", width: 60 },
                    { data: "Group", name: "Group", title: "Group", orderable: false, width: 120 }
                ]
                , rowId: 'HeaderId'
            });
    
            $('#Table1 tbody').on('click', 'td img', function () {
    
                var tr = $(this).closest('tr');
                var row = table1.row(tr);
    
                if (row.child.isShown()) {
                    // This row is already open - close it
                    destroyChild(row);
                    tr.removeClass('shown');
                }
                else {
                    // Open this row
                    createChild(row);
                    tr.addClass('shown');
                }
    
            });
        });
    
        function createChild(row) {
            // This is the table we'll convert into a DataTable
            var table2 = $('<table class="display" width="100%"/>');
    
            // Display it the child row
            row.child(table2).show();
    
            // Initialise as a DataTable
            var usersTable = table2.DataTable({
                async: true,
              serverSide: false, // for process server side
              scrollX: false, //Enable Horizonal Scroll
              deferRender: true, // deferred rendering
              processing: dataTablesprocessing, // for show progress bar
              filter: true,
              orderMulti: true,
              info: false,
              paging: false,
              select: false,
              autoWidth: dataTablesautoWidth,
              responsive: dataTablesresponsive,
              data: dataSet2,
                order: [[0, 'asc']],
                columnDefs: [],
                columns: [
                    { data: "LineNumber", name: "LineNumber", title: "#", autoWidth: true },
                    { data: "HeaderId", name: "HeaderId", title: "Header ID", autoWidth: true },
                    { data: "ProductId", name: "ProductId", title: "Product ID", autoWidth: true }
                ]
            });
        }
    
        function destroyChild(row) {
            var table2 = $("table", row.child());
            table2.detach();
            table2.DataTable().destroy();
    
            // And then hide the row
            row.child.hide();
        }
    </script>
    

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

  • allanallan Posts: 61,821Questions: 1Answers: 10,127 Site admin

    Right - I think at least part of the issue is that you have a conflict between the Responsive control and your child row control. By default (responsive: true which is what you have) Responsive will show a child row when clicking on the first column in the table (if the table is collapsed). But you also have your event handler for the child row editing on the first column.

    What I would suggest is that you separate the two. Make the Responsive control in its own column and likewise the child row.

    Additionally, because you can't mix Responsive's child rows with your own child rows, you should use a modal to display the hidden details from the row. Otherwise, again, you'd have a conflict.

    Allan

  • INRINR Posts: 20Questions: 2Answers: 1

    Thanks Allan. I will try the "responsive control its own column"

    I couldnt understand why it fails when using AJAX and working fine when we pass the JSON array as data set ?

This discussion has been closed.