42

Is there a way to refresh a single Kendo grid row without refreshing the whole datasource or using jQuery to set the value for each cell?

numaroth
  • 1,295
  • 4
  • 25
  • 36
rafoo
  • 1,095
  • 1
  • 11
  • 14

4 Answers4

58

How do you define the row that you want to update? I'm going to assume that is the row that you have selected, and the name of the column being updated is symbol.

// Get a reference to the grid
var grid = $("#my_grid").data("kendoGrid");

// Access the row that is selected
var select = grid.select();
// and now the data
var data = grid.dataItem(select);
// update the column `symbol` and set its value to `HPQ`
data.set("symbol", "HPQ");

Remember that the content of the DataSource is an observable object, meaning that you can update it using set and the change should be reflected magically in the grid.

Iman Mahmoudinasab
  • 6,861
  • 4
  • 44
  • 68
OnaBai
  • 40,767
  • 6
  • 96
  • 125
  • 4
    What should we do if their is a custom template on a cell, which is un-editable, and that template calls a function. Calling set on the data item does not seem to redraw the template. – jonperl Dec 06 '12 at 20:05
  • @jonperl I suggest you to ask it as a different question in order to make sure that others than me see it and have the opportunity of answering it. Anyway I tried it with templates and it worked. So, please post some code showing what you tried and showing what fails. – OnaBai Dec 06 '12 at 20:53
  • NOTE: 'kendoDataGrid' is now called 'kendoGrid' (or perhaps it always was) – Simon_Weaver Apr 29 '13 at 06:11
  • @OnaBai when you say 'the content of the DataSource is an observable object' this only applies if you want to update the entire data set right and not just a single row? AFAIK I need to call 'data.set' for each column when updating a specific/single row – Simon_Weaver Apr 29 '13 at 06:35
  • @Simon_Weaver, you are right! But that's the same for any _Observable_ object. _Observable_ is not something built-in in JavaScript language, the only way to intercept changes in an object is using some method that checks when a value is assigned and who is willing to know about it (the UI) – OnaBai Apr 29 '13 at 06:41
  • 4
    @OnaBai thanks. also it turns out that if a column is set to be non-editable in the model (eg. `model.Fields[0].editable == false` then if you call `data.set('ProductName', 'Cat')` on that column it won't be updated in the grid. I assume this could be fixed by a custom template if really necessary – Simon_Weaver Apr 29 '13 at 07:24
  • Might be arguable but what does not "editable" mean? In this context and keeping in mind the UI part of KendoUI I try to understand that is about UI and not a full programming interface. The support for "Observable" objects is due to the fact that you need to update the UI and then we (the programmers) want to use it extending its scope... – OnaBai Apr 29 '13 at 07:31
  • I've tried both @OnaBai and Adam Yaxley's solutions. OnaBai's solution works to begin with but ends with all kinds of scrolling and current row and cell selection issues. Adam's solutions works beautifully with no side-effects. – stricq Sep 20 '15 at 18:12
  • @OnaBai var select = grid.select(); will not work in a popup editor. how can i determine which row is being edited? – agDev Nov 16 '16 at 22:06
34

data.set will actually refresh the entire grid and send a databound event in some cases. This is very slow and unnecessary. It will also collapse any expanded detail templates which is not ideal.

I would recommend you to use this function that I wrote to update a single row in a kendo grid.

// Updates a single row in a kendo grid without firing a databound event.
// This is needed since otherwise the entire grid will be redrawn.
function kendoFastRedrawRow(grid, row) {
    var dataItem = grid.dataItem(row);

    var rowChildren = $(row).children('td[role="gridcell"]');

    for (var i = 0; i < grid.columns.length; i++) {

        var column = grid.columns[i];
        var template = column.template;
        var cell = rowChildren.eq(i);

        if (template !== undefined) {
            var kendoTemplate = kendo.template(template);

            // Render using template
            cell.html(kendoTemplate(dataItem));
        } else {
            var fieldValue = dataItem[column.field];

            var format = column.format;
            var values = column.values;

            if (values !== undefined && values != null) {
                // use the text value mappings (for enums)
                for (var j = 0; j < values.length; j++) {
                    var value = values[j];
                    if (value.value == fieldValue) {
                        cell.html(value.text);
                        break;
                    }
                }
            } else if (format !== undefined) {
                // use the format
                cell.html(kendo.format(format, fieldValue));
            } else {
                // Just dump the plain old value
                cell.html(fieldValue);
            }
        }
    }
}

Example:

// Get a reference to the grid
var grid = $("#my_grid").data("kendoGrid");

// Access the row that is selected
var select = grid.select();
// and now the data
var data = grid.dataItem(select);

// Update any values that you want to
data.symbol = newValue;
data.symbol2 = newValue2;
...

// Redraw only the single row in question which needs updating
kendoFastRedrawRow(grid, select);

// Then if you want to call your own databound event to do any funky post processing:
myDataBoundEvent.apply(grid);
Adam Yaxley
  • 670
  • 1
  • 7
  • 13
  • 3
    What if you aren't doing editing on the grid itself, but instead in a popup. How do you determine the row that is being edited? – Scott Aug 05 '15 at 03:59
  • I do get myDataBoundEvent is a function variable in the code snippet above. But what kind of code actually goes into that function? Is there a live example of that I can look at? I am currently having code above without the apply call in the end after invoking the kendoFastRedrawRow method invocation and I see a spinning wheel, seeming to suggest that the browser is still waiting for something. Any pointers? – Sudhir Nov 02 '16 at 20:14
  • @Scott did you find a solution on - How do you determine the row that is being edited in a popup ? – agDev Nov 16 '16 at 22:09
  • No idea. This was over a year ago. :) – Scott Nov 17 '16 at 16:09
  • @Adam Yaxley, This is working fine for me, but is there any way to refresh all the columns in the row using json instead of dong each column like data.symbol = newValue, because my grid contains up to 60 columns? – Gurunadh Mar 16 '17 at 13:54
  • 1
    This approach worked well with a plain grid, but another grid I had included columns that used templates with angular 1 parts, it couldn't handle this. – user2590928 Aug 11 '17 at 00:31
  • This is a very interesting input and i tested it. It works well for a lot of things. In my case, with groups and aggregated sum it does not work on dataBound. Thanks for your input. my test: https://dojo.telerik.com/ikiDIZIY – Severin Aug 25 '21 at 16:14
  • @agDev If you're editing from a pop-up and working on the dataItem, you can use the uid property to get the row object like this var uiRow = grid.tbody.find("tr[data-uid='" + dataItem.uid + "']")[0]; – Prashanth Subramanian Jun 08 '23 at 00:02
9

I found a way to update the grid dataSource and show in the grid without refreshing all the grid. For example you have a selected row and you want to change column "name" value.

//the grid
var grid = $('#myGrid').data('kendoGrid');    
// Access the row that is selected
var row = grid.select();
//gets the dataItem
var dataItem = grid.dataItem(row);
//sets the dataItem   
dataItem.name = 'Joe';
//generate a new row html
var rowHtml = grid.rowTemplate(dataItem);
//replace your old row html with the updated one
row.replaceWith(rowHtml);
Srulik
  • 106
  • 1
  • 3
  • I don't know if they added the feature since you wrote your answer, but if you replace dataItem.name with dataItem.set("Name", "Joe") then you don't need to re-render the grid. It will update itself. – John Lord Jun 07 '21 at 13:53
  • Your right it will update the grid like in the different Onas' answer but it will re-render the entire grid and if you have filter it will hide the line or move it to other location (in sort). – Srulik Oct 11 '21 at 12:13
  • Perfect! I added the following line of code afterwards to re-select the previously selected row: `grid.select(grid.table.find("[data-uid=" + dataItem.uid + "]"));` – Randy Burden Jun 30 '22 at 22:03
2
updateRecord(record) {
    const grid = $(this.el.nativeElement).data('kendoGrid');
    const row = grid.select();
    const dataItem = grid.dataItem(row);
    for (const property in record) {
      if (record.hasOwnProperty(property)) {
        dataItem.set(property, record[property]);
      }
    }
  }
FireDog
  • 291
  • 3
  • 3