As explained in this post, the current (as of v9.0 build 3272) Aware parser for grids saves the edits made in a grid with inline editing when a row operation for that grid is invoked, but the save process is an asynchronous process running simultaneous with the process for the row operation. This may mean that the process for the row operation does not use the latest state of the BO to which the operation applies.
This can be solved by including the javascript below in the render script for the grid. The general principle is relatively easy:
The code adds an event handler for a click on the table body (one level lower than the table as a whole).
When a row operation is clicked, the event handler saves the link for that operation, syncs the grid with the datasource, and after that sync is completed it triggers a second click on the same operation.
There is however some additional complexity, because as a result of the sync of the datasource not only the contents of the grid rows are refreshed but also the links containing the row operation. This means that the row operation links immediately prior to the sync cannot be used to trigger a second click after the sync. You need to get the refreshed link for the same operation after the data sync. To add with this process, I created a helper class RowOperation with properties and methods that deal with saving and refreshing the link and triggering the click. Also, a flag is needed to signal that the (second) click is made by the code, to avoid that you get in an endless loop.
Here is the code:
// Current widget is a Kendo UI grid (because it is included as Render script of the grid)
const grid = widget;
// Attach Kendo grid event handlers
grid.dataSource.bind("sync", onDataSourceSync);
// Attach jQuery event handlers
grid.tbody.on("click", onTableClick);
class RowOperation {
static #isClicked = false; // flag to signal that the row operation has been invoked by code
static #link = null; // holds the (jQuery) button element <a> for the row operation, if clicked
static #rowIndex = -1; // row index of the row that was clicked on the save button
static #dataOperidx = -1; // operation index of the row operation that was clicked on
static #grid = grid; // reference to the grid
static get link() {
return this.#link;
}
static set link(link) {
if (link && link.hasClass("aw-link") && link.attr("data-operidx") != undefined) {
this.#link = link;
this.#rowIndex = link.closest("tr").index();
this.#dataOperidx = link.attr("data-operidx");
}
}
static get isClicked() {
return this.#isClicked;
}
static resetClicked() {
this.#isClicked = false;
}
static triggerClick() {
if (this.#link) {
this.#isClicked = true;
this.#link.trigger("click");
}
}
static sync() {
if (this.#link) {
this.#link = this.#grid.tbody
.find("tr")
.eq(this.#rowIndex)
.find("a.aw-link[data-operidx='" + this.#dataOperidx + "']");
if (this.#link.length == 0) {
this.#link = null;
}
}
}
}
// Event handler for dataSource sync event
function onDataSourceSync() {
RowOperation.sync();
}
// Event handler for click on the table
function onTableClick(event) {
if (RowOperation.isClicked) {
// Row operation is 'clicked' by code. Proceed with defined operation for the link (let event bubble to the Aware handler for the link)
RowOperation.resetClicked();
return;
}
let target = $(event.target).closest("a.aw-link[data-operidx]");
if (target.length == 1 && grid.dataSource.hasChanges()) {
event.stopImmediatePropagation(); // prevent event bubbling
RowOperation.link = target;
jQuery
.when(grid.dataSource.sync())
.done(() => { RowOperation.triggerClick(); })
.fail((error) => { console.error("Data source sync failed: ", error); });
}
}
The essence is in the code
jQuery
.when(grid.dataSource.sync())
.done(() => { RowOperation.triggerClick(); })
Because the dataSource.sync() function returns a Promise, this can be used to trigger the click only after the sync is completed.
Furthermore, note that the onDataSourceSync event handler, calling RowOperation.sync(), is required to make sure that the link is refreshed after the dataSource is synced. Otherwise the trigger will not work.
I tested this with Firefox 129.0.2, Google Chrome 127.0.6533 and Microsoft Edge 127.0.2651.
I developed this for the purpose of row operations of the 'Start Process' type (i.e. running a process that takes the BO in the grid as input), but because of the general nature I think it will also work for other types of row operations.
Note however that this assumes that the row operations are displayed as separate icons in the grid. If you combine the row operations in a menu on the grid row, it will probably not work due to the different page layout.
While this code works to solve the issue, I think it would be preferable if the Aware parser would be amended such that the row operation is invoked only after the datasource sync is completed. I submitted a request for this in this post in the Wish List section.