This is a migrated thread and some comments may be shown as answers.

Changing values of grid in Javascript takes a long time

6 Answers 218 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Ruben
Top achievements
Rank 1
Ruben asked on 18 Jun 2018, 02:09 PM

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

Sort by
0
Viktor Tachev
Telerik team
answered on 20 Jun 2018, 11:11 AM
Hello Ruben,

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
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Ruben
Top achievements
Rank 1
answered on 21 Jun 2018, 03:25 PM

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

 

0
Viktor Tachev
Telerik team
answered on 22 Jun 2018, 11:20 AM
Hi 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
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Ruben
Top achievements
Rank 1
answered on 22 Jun 2018, 03:35 PM

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

0
Ruben
Top achievements
Rank 1
answered on 22 Jun 2018, 04:42 PM

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();
0
Viktor Tachev
Telerik team
answered on 26 Jun 2018, 11:51 AM
Hi Ruben,

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
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
Grid
Asked by
Ruben
Top achievements
Rank 1
Answers by
Viktor Tachev
Telerik team
Ruben
Top achievements
Rank 1
Share this question
or