Updating parent data grid from child grid

1 Answer 31 Views
Data Source Grid
Y
Top achievements
Rank 1
Y asked on 10 Jun 2025, 11:22 AM

Hello

I have a grid and each row can be expanded, using detailInit, to show an inner grid. 

I fetch the data beforehand so that I can populate the grid using local data.

In inner grid I have a column with a delete button  - using template I call a delete function passing this as a parameter.



// column definition
 {
                    field: "delete",
                    title: "Delete",
                    width: 50,
                    template: "<span class='delete' onclick='delete(this)'><img src='.delete_icon.png'/></span>"
},

my delete function :


function delete(e) {
            let Loader = KENDO.KendoLoader($("body"));
            try {
                Loader.Show();
                let row = $(e).closest("tr");
                let grid = $(e).closest(".innerGrid");

                let dataItem = KENDO.KendoGrid(grid).GetDataItem(row);
                let innerRowId= dataItem.id;

                let parentRow = row.parent().closest(".k-detail-row").prev();
                let parentDataItem = KENDO.KendoGrid($("#ParentGrid")).GetDataItem(parentRow);

                KENDO.KendoGrid(grid).DeleteUI([innerRowId]); // DeleteUI gets array of ids to delete , implemented below
               
                // if no rows remain in inner grid, I need to update a column's value in the parent row
                if (KENDO.KendoGrid(grid).HasRows() == false) {
                    grid.hide();
                    grid.siblings(".noRecordsFound").show();

                     let updatedDataObj = {
                            id: parentDataItem.id,
                            someColumnOnParentRow: null
                        }

                        KENDO.KendoGrid($("#ParentGrid")).UpdateUI([updatedDataObj]); // UpdateUI gets array of objects to update, implemented below
                }
            }
            catch (error) {
                debugger;
                console.log(error.message);
            }
            finally {
                Loader.Hide();
            }
        }

We have created a own KENDO wrapper script for different widgets. Here is the kendoGrid code: 


let KENDO = {
  KendoComponent(jQueryElement, component, options = null) {

        let kendoComponent = {};

        kendoComponent.InitKendoComponent = function () {
            let kComponent = jQueryElement.data(component);
            if (!kComponent) {
                if (options) {
                    kComponent = jQueryElement[component](options).data(component);
                }
                else {
                    kComponent = jQueryElement[component]().data(component);
                }
            }
            return kComponent;
        };

        return kendoComponent;
    },

   KendoGrid(jQueryElement, options = null) {

        let kendoGrid = {};

        let kGrid = KENDO.KendoComponent(jQueryElement, "kendoGrid", options).InitKendoComponent();
        if (options)
            kGrid.setOptions(options);

        kendoGrid.SetOptions = function (options) {
            kGrid.setOptions(options);
            return kendoGrid;
        }

        kendoGrid.GetData = function () {
            return Array.from(kGrid.dataSource.data());
        }

        kendoGrid.GetDataItem = function (jQueryTableRow) {
            return kGrid.dataItem(jQueryTableRow);
        }

        kendoGrid.UpdateUI = function (dataToUpdate = []) {
            dataToUpdate.forEach(obj => {
                let dataItem = kGrid.dataSource.get(obj.id);
                if (dataItem) {
                    for (let prop in obj) {
                        if (prop !== "id") {
                            dataItem.set(prop, obj[prop]);
                        }
                    }
                } 
            });
            return kendoGrid;
        }

        kendoGrid.DeleteUI = function (idsToDelete = []) {
            idsToDelete.forEach(id => {
                let dataItem = kGrid.dataSource.get(id);
                if (dataItem)
                    kGrid.dataSource.remove(dataItem);
            });
            return kendoGrid;
        };

        kendoGrid.HasRows = function () {
            return kGrid.dataSource.data().length > 0;
        }

        return kendoGrid;
    }
  
}

It appears that UpdateUI does not function as it should.

When I test I notice that when the last remaining row of inner grid is deleted, the parent row's column is indeed updated to null, the No Records Found message is shown instead of the inner grid, the parent row gets collapsed, and when I expand it the inner grid is shown with the last remaining row.

Suprisingly, if I comment out the UpdateUI line, the inner grid's row gets deleted, without collapsing the inner grid and the No Records Found message is shown as intended (the parent row's column does not get updated in this case, obviously).

Is it a bug in Kendo ? or am I doing something wrong?

1 Answer, 1 is accepted

Sort by
0
Neli
Telerik team
answered on 13 Jun 2025, 07:47 AM

Hi,

It is really hard to be sure about the reason for the observed behavior, as in the provided snippet, there is quite a lot of custom implementation, and the code is not runnable. To be able to help appropriately, it would be very helpful if you could provide us with a runnable example that demonstrates the issue. This way, we could investigate locally and provide assistance. 

However, below you will find some suggestions on the things that you could check on your end:

  • Unexpected Collapse: The issue arises when the UpdateUI function is called, causing the parent row to collapse after updating the parent grid's column to null. This behavior suggests that the grid's data-binding mechanism might be reacting to the data update in a way that triggers the collapse.

Possible Solutions

  1. DataSource Synchronization: Ensure that the data source of the parent grid is correctly synchronized after the update. The collapse might be triggered by how the grid's data source handles changes.

  2. Avoid UI Triggers: Consider restructuring your UpdateUI logic to avoid triggering events that may cause the collapse. You could update the data directly in the data source without invoking methods that might lead to unintended UI updates.

  3. Manual Refresh: After updating the parent row, manually refresh the grid using the refresh() method to ensure that the UI reflects the changes correctly without collapsing.

  4. Conditional UI Update: Add a condition to prevent the collapse of the parent row. Check if the inner grid is empty before updating the parent row, and ensure the inner grid remains visible with the "No Records Found" message.

Code Adjustments

Here's a code snippet illustrating how to handle the manual refresh:

function delete(e) {
    let Loader = KENDO.KendoLoader($("body"));
    try {
        Loader.Show();
        let row = $(e).closest("tr");
        let grid = $(e).closest(".innerGrid");
       .....

        if (KENDO.KendoGrid(grid).HasRows() == false) {
            grid.hide();
            grid.siblings(".noRecordsFound").show();
            let updatedDataObj = {
                id: parentDataItem.id,
                someColumnOnParentRow: null
            };
            KENDO.KendoGrid($("#ParentGrid")).UpdateUI([updatedDataObj]);
            KENDO.KendoGrid($("#ParentGrid")).refresh(); // Refresh the parent grid
        }
    } catch (error) {
        console.log(error.message);
    } finally {
        Loader.Hide();
    }
}

The behavior you are experiencing is not necessarily a bug but could be related to how the data source updates are handled within the grid. By implementing the suggested solutions, you should be able to prevent the unexpected collapse of the parent row.

Regards,
Neli
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Y
Top achievements
Rank 1
commented on 13 Jun 2025, 09:20 AM

Hello, 

Thank you for your answer.

Things I've tried but did not solve our problem -

1. adding refresh to grid:

kendoGrid.UpdateUI = function (dataToUpdate = []) { dataToUpdate.forEach(obj => { let dataItem = kGrid.dataSource.get(obj.id); if (dataItem) { for (let prop in obj) { if (prop !== "id") { dataItem.set(prop, obj[prop]); } } } });

kGrid.refresh(); return kendoGrid; }

 

2. changing .set() of dataItem to a simple assignment : 

[Interestingly, if I use this option (without adding refresh), I notice the last remaining row of inner grid is deleted as intended, the parent row remains expanded, but the value of parent row does not get removed]

kendoGrid.UpdateUI = function (dataToUpdate = []) { dataToUpdate.forEach(obj => { let dataItem = kGrid.dataSource.get(obj.id); if (dataItem) { for (let prop in obj) { if (prop !== "id") { dataItem[prop] = obj[prop]; } } } }); return kendoGrid; }

Y
Top achievements
Rank 1
commented on 13 Jun 2025, 11:01 AM | edited

Edit: here is a demo using the latest version of kendo UI. 

I was able to reproduce the issue

 

https://jsfiddle.net/8os1zpm2/

Neli
Telerik team
commented on 18 Jun 2025, 08:18 AM

Hi,

Thank you for sharing a runnable sample that illustrates the issue. I'll review it and get back to you in the thread by tomorrow.

Regards,

Neli

Neli
Telerik team
commented on 19 Jun 2025, 06:11 AM

Hi,

I would suggest using the approach described in the following Knowledge Base article for Refresh Particular Rows without Rerendering the Entire Grid:

- https://www.telerik.com/kendo-jquery-ui/documentation/knowledge-base/grid-update-particular-row-without-refresh

You can use the function from the article and simplify it in case you scenario allows it. Below is an example:

  function kendoFastReDrawRow(grid, row) {
        var dataItem = grid.dataItem(row);

        var rowChildren = $(row).children('td[role="gridcell"]');

        for (var i = 0; i < grid.columns.length; i++) {
          var column = grid.columns[i];
          var template = column.template;
          var cell = rowChildren.eq(2);
          var fieldValue = dataItem[column.field];
          cell.html(fieldValue);
        }
      }

Then in the deleteExclusion function you can call the kendoFastReDrawRow:

kendoFastReDrawRow(parentGrid, parentRow);

The above is demonstrated in the Dojo linked here - https://dojo.telerik.com/zKYTOCjK

I hope this helps. 

Regards,

Neli

Tags
Data Source Grid
Asked by
Y
Top achievements
Rank 1
Answers by
Neli
Telerik team
Share this question
or