Changing values of grid in Javascript takes a long time

7 posts, 0 answers
  1. Ruben
    Ruben avatar
    22 posts
    Member since:
    Sep 2017

    Posted 18 Jun 2018 Link to this post

    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();
  2. Viktor Tachev
    Admin
    Viktor Tachev avatar
    2491 posts

    Posted 20 Jun 2018 Link to this post

    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.
  3. Ruben
    Ruben avatar
    22 posts
    Member since:
    Sep 2017

    Posted 21 Jun 2018 in reply to Viktor Tachev Link to this post

    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

     

  4. Viktor Tachev
    Admin
    Viktor Tachev avatar
    2491 posts

    Posted 22 Jun 2018 Link to this post

    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.
  5. Ruben
    Ruben avatar
    22 posts
    Member since:
    Sep 2017

    Posted 22 Jun 2018 in reply to Viktor Tachev Link to this post

    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

  6. Ruben
    Ruben avatar
    22 posts
    Member since:
    Sep 2017

    Posted 22 Jun 2018 Link to this post

    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();
  7. Viktor Tachev
    Admin
    Viktor Tachev avatar
    2491 posts

    Posted 26 Jun 2018 Link to this post

    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.
Back to Top