Grid editRow() and modifying the row data before displaying

1 Answer 28 Views
Grid
IoM
Top achievements
Rank 1
IoM asked on 12 Mar 2025, 08:42 PM

We have a Grid set to popup edit mode, and Kendo internally calls editRow() when we click on an "Edit" command button we define in one of the columns..  As part of our row editing process, we would like to refresh the row's data in the datasource from the remote server, so that the user is editing fresh, current data for the row.  It appears that even the beforeEdit event is too late for this, as the popup editor has already used the existing values in the data record, and getting the datasource to reload the data item the row uses won't affect the values displayed in the editor (although the datasource is indeed updated).  So what we did in our beforeEdit() handler was something like this:

  1. call e.preventDefault(), which is intended to eventually cancel out the editRow() call that Kendo made from our button click.
  2. get as "row" the "tr" element from e.sender.tbody that has the
  3. run some code that updates the one item in the datasource (e.model) - the AJAX call is done in a deferred promise.
  4. in the then() handler of that, call e.sender.editRow(row), which should make a new editing call, replacing the one we aborted with preventDefault().

This may be a terrible hack, but it seemed to work with Kendo 2021.2.526.  When we replaced that with Kendo 2025.1.227, it fails.  We get a Javascript error like this:

Uncaught TypeError: Cannot read properties of undefined (reading 'parent')
    at init.editRow (kendo.2025.1.227.all.min.js:9:1918996)
    at init._editCommandClick (kendo.2025.1.227.all.min.js:9:1911991)
    at HTMLDivElement.dispatch (jquery.min.js:3:12444)
    at r.handle (jquery.min.js:3:9173)

and the editRow line is something like this:

                a = r.editView ? r.editView.element : "popup" === s ? r._editContainer.parent() : r._editContainer,

where "r" is effectively "this", the grid widget.  It looks like when Kendo does its own editRow() call, it may be stashing the popup window as "_editContainer", and does a .parent() dereference to get the grid container that it would get directly in the non-popup case.  But when we make our own editGrid() call, either the context is slightly different and the Kendo code doesn't stash the popup window, or there's some extra state being kept in the newer Kendo code that isn't cleared by our preventDefault() call, and is still there when we make our own editRow() call before our beforeEdit handler returns control to Kendo, or something like that.

We could try either using our own button (which we would probably have to style to match the classes Kendo give the edit button it produces itself), which could call editRow(), or maybe attach a click handler to Kendo's button to do our data refresh before things continue on to Kendo's click handling, so that we get in there before Kendo calls editRow().  But I was wondering if there was some clean way of hooking into the row edit process to refresh our data before the popup window looks at it?

1 Answer, 1 is accepted

Sort by
0
Nikolay
Telerik team
answered on 17 Mar 2025, 12:29 PM

Hi Aaron,

You're right that the beforeEdit event occurs too late since Kendo has already populated the popup editor with stale data by that point. The issue with calling editRow() again after canceling the original edit is that Kendo internally maintains state about the editing process, and your preventDefault() workaround interferes with that in newer versions.

I can suggest instead of interfering with Kendo's internal edit process, we can intercept the edit command before it triggers editRow() and fetch fresh data. Here's how:

1. Attach a click handler to the Edit button.
2. Intercept the click event, fetch fresh data via AJAX.
3. Update the DataSource item with fresh data.
4. Call editRow() manually after data is refreshed.

$(document).ready(function () {
    var grid = $("#grid").kendoGrid({
        dataSource: {
            transport: {
                read: function (options) {
                    // Simulate fetching data from a remote server
                    setTimeout(function () {
                        options.success([
                            { id: 1, name: "John Doe", age: 30 },
                            { id: 2, name: "Jane Smith", age: 25 }
                        ]);
                    }, 100);
                }
            },
            schema: {
                model: {
                    id: "id",
                    fields: {
                        id: { type: "number" },
                        name: { type: "string" },
                        age: { type: "number" }
                    }
                }
            }
        },
        editable: "popup",
        columns: [
            { field: "id", title: "ID", width: "50px" },
            { field: "name", title: "Name", width: "150px" },
            { field: "age", title: "Age", width: "100px" },
            {
                command: {
                    name: "edit",
                    text: "Edit",
                    click: function (e) {
                        e.preventDefault(); // Stop Kendo's default editRow call

                        var grid = $("#grid").data("kendoGrid");
                        var row = $(e.currentTarget).closest("tr");
                        var dataItem = grid.dataItem(row);

                        // Fetch fresh data from the server before opening the editor
                        $.ajax({
                            url: "/get-latest-data", // Replace with your API URL
                            method: "GET",
                            data: { id: dataItem.id },
                            success: function (freshData) {
                                // Update the Kendo DataSource item with fresh data
                                grid.dataSource.pushUpdate(freshData);

                                // Open the edit popup with the updated data
                                grid.editRow(row);
                            },
                            error: function () {
                                alert("Failed to fetch latest data.");
                            }
                        });
                    }
                },
                title: "Actions",
                width: "100px"
            }
        ]
    }).data("kendoGrid");
});

Regards,
Nikolay
Progress Telerik

Enjoyed our products? Share your experience on G2 and receive a $25 Amazon gift card for a limited time!

IoM
Top achievements
Rank 1
commented on 18 Mar 2025, 04:14 PM

It looks like recent versions of Kendo jQuery don't call the click handler in this example.  I tweaked it into a Dojo test, with an alert at the top of the click function, and it works in 2023.1.117, but the click handler function doesn't seem to get called in 2023.1.314 or higher.  I'm not sure if this was a bug introduced, or some sort of change to the Grid API specs at that point - I'm going to take a look at the release notes.

It looks like something specific to the "edit" command - I added a "details" command with a click handler, and that button calls the function in all versions of Kendo.

https://dojo.telerik.com/FBHGkwGk

Nikolay
Telerik team
commented on 21 Mar 2025, 12:49 PM

Hi Aaron,

There has been a design change in the click handlers for the built-in command with v.2023.1.314. They can no longer be overridden with the columns command.click property. It generally does not make sense to override the internal command. 

If you wish to have a custom command you can use a custom command and write the desired logic.

Regards,

Nikolay

Tags
Grid
Asked by
IoM
Top achievements
Rank 1
Answers by
Nikolay
Telerik team
Share this question
or