Hi,
I have an MVC grid that has a custom bulk edit mode. The user selects the column of the grid and the value that they want to update. They then select the rows of the grid that they way to update, and press a button to update the grid.
It works fine; however, when performing an update of a couple hundred rows the grid takes a long time to update.
If I call the following code say, 500 times it will take 1-1.5 minutes to complete. Is there a faster way to change the values of a grid programmatically in Javascript?
grid.editCell(cell);
dataItem.set(columnName_Grid1, templateSelectionValue_Grid1);
grid.closeCell();
6 Answers, 1 is accepted
Please have in mind that it is not necessary to open and close each cell for editing when changing the value programmatically. In order to improve the performance when changing multiple values in the Grid I would suggest using only the set() method. When the changes are complete you can send them to the server by calling dataSource.sync().
Also, it is recommended to have batch mode enabled so multiple changes can be sent to the server with a single request.
Give the modification a try and let me know how the behavior changes.
Regards,
Viktor Tachev
Progress Telerik
Hi Viktor,
Thank you for the tips. My grid is using batch mode.
Originally, my code looped through all the selected rows and then called grid.saveChanges()after all the necessary changes were made.
Option #1: (RunTime Approx: 01:10, 529 cells changes)
var
grid = $(
'#grid2'
).data(
'kendoGrid'
);
var
rows = grid.tbody[0].rows;
if
(templateSelectionValue_Grid2 ==
"null"
) {
templateSelectionValue_Grid2 =
""
;
}
for
(
var
rowIndex
in
rows) {
if
(rowIndex ===
"length"
) {
break
;
}
if
(rows[rowIndex].className.includes(
"k-state-selected"
)) {
// find the cell to update in grid
var
dataItem = grid.dataItem(rows[rowIndex]);
var
row = grid.tbody.find(
"tr[data-uid="
+ dataItem.uid +
"]"
);
var
cellIndex = grid.element.find(
"th[data-field = '"
+ columnName_Grid2 +
"']"
).index();
var
cell = row.find(
"td:eq("
+ cellIndex +
")"
);
grid.editCell(cell);
dataItem.set(columnName_Grid2, templateSelectionValue_Grid2);
grid.closeCell();
}
}
// save edited data
grid.saveChanges();
Option #2: (RunTime Approx: 05:56, 529 cells changes)
var
grid = $(
'#grid1'
).data(
'kendoGrid'
);
var
rows = grid.tbody[0].rows;
if
(templateSelectionValue_Grid1 ==
"null"
) {
templateSelectionValue_Grid1 =
""
;
}
var
dataItems =
new
Array();
var
itemCount = 0;
for
(
var
rowIndex
in
rows) {
if
(rowIndex ===
"length"
) {
break
;
}
if
(rows[rowIndex].className.includes(
"k-state-selected"
)) {
var
dataItem = grid.dataItem(rows[rowIndex]);
dataItems[itemCount] = dataItem;
itemCount++;
}
}
for
(
var
itemCount
in
dataItems) {
dataItems[itemCount].set(columnName_Grid1, templateSelectionValue_Grid1);
}
// save edited data
grid.dataSource.sync();
So, after making the suggested changes, it takes almost 6x longer to update 529 items/cells in my datasource. What do you think?
Best,
Ruben
The code in the second snippet iterates through items two times - it loops through all rows and then all items that are selected. Note that this is not necessary as there is a built-in method that will return all selected items.
In order to change the values for a cell in all selected rows you can use logic similar to the following:
var
grid = $(
'#grid2'
).data(
'kendoGrid'
);
var
selectedRows = grid.select();
if
(templateSelectionValue_Grid2 ==
"null"
) {
templateSelectionValue_Grid2 =
""
;
}
for
(
var
i = 0; i < selectedRows.length; i++) {
var
dataItem = grid.dataItem(selectedRows[i]);
dataItem.set(columnName_Grid2, templateSelectionValue_Grid2);
}
Let me know how this works on your end.
Regards,
Viktor Tachev
Progress Telerik
Hi Viktor,
The reason I loop through twice is because when I call dataItem.set(), it removes the selected rows from the grid if the respective grid cell is not opened prior to calling dataItem.set(). This means that only the first value is changed when calling your code above. In my implementation I had to save the state of the dataItems in order to call dataItem.set() on more than 1 field.
Additionally, I think it's worth noting that if I run the below code with the dataItem.set() commented out the run time for 529 items is 0:03 seconds. So the dataItem.set() method takes almost 6 minutes to call 529 times. The rest of the code is for the most part negligible until we can get the functionality of the dataItem.set() method to run much faster.
var
grid = $(
'#grid1'
).data(
'kendoGrid'
);
var
rows = grid.tbody[0].rows;
if
(templateSelectionValue_Grid1 ==
"null"
) {
templateSelectionValue_Grid1 =
""
;
}
var
dataItems =
new
Array();
var
itemCount = 0;
for
(
var
rowIndex
in
rows) {
if
(rowIndex ===
"length"
) {
break
;
}
if
(rows[rowIndex].className.includes(
"k-state-selected"
)) {
var
dataItem = grid.dataItem(rows[rowIndex]);
dataItems[itemCount] = dataItem;
itemCount++;
}
}
for
(
var
itemCount
in
dataItems) {
// dataItems[itemCount].set(columnName_Grid1, templateSelectionValue_Grid1);
}
// save edited data
grid.dataSource.sync();
Best,
Ruben
Hi Viktor,
I got the issue resolved. The .Set() can get computationally heavy if you're updating many rows. Referring to this post (Similar Issue discussion):
"Changing a value using set will trigger the data source change event and the whole grid will be rebound. If you want to perform lots of updates you can avoid the set method and call the grid's refresh method when the update is finished:"
This is my updated code: (RunTime Approx: a few seconds, 529 cells changes)
if
(templateSelectionValue_Grid1 ==
"null"
) {
templateSelectionValue_Grid1 =
""
;
}
var
grid = $(
'#grid1'
).data(
'kendoGrid'
);
var
selectedRows = grid.select();
for
(
var
i = 0; i < selectedRows.length; i++) {
var
dataItem = grid.dataItem(selectedRows[i]);
dataItem.dirty =
true
;
dataItem.dirtyFields = dataItem.dirtyFields || {};
dataItem.dirtyFields[columnName_Grid1] =
true
;
dataItem[columnName_Grid1] = templateSelectionValue_Grid1;
}
grid.refresh();
grid.saveChanges();
I am glad that you have the functionality up and running. Thank you for sharing the approach you went for and the cause of the delay.
Let us know if you have additional queries.
Regards,
Viktor Tachev
Progress Telerik