I have an MVC grid that has an Ajax datasource with InCell editing. After the grid loads we want to be able to update the contents of cells with JavaScript. So the user will enter a value in a textbox. Click a button that will execute JavaScript. The JavaScript will then update the cells in the grid with the value from the textbox. The idea being that this will save the user from typing the same value into every cell.
Below is the JavaScript function I have. It's looping through the grid and changing the value in cell named "NonOutageCost". If I don't refresh the grid - then I don't see that the value has changed until I click in the cell. After I click in the cell - then it shows me the value the JavaScript function set. But it doesn't show the red dirty flag indicator. If I refresh the grid - then it shows me the value the JavaScript function set. But it doesn't show me the red dirty flag indicator.
Is there a way to have a JavaScript function that is executed by a button click change the cell contents and set the dirty flag indicator? If so, could you show me an example. I've spent a lot of time researching this and looking at the documentation. But I haven't found an example like this. Most of the examples I saw show doing something like this in a databound event. But that won't work in this case. Thanks for your help.
function myFunction() {
alert("Function executes when button is clicked");
var vgrid = $("#grid").data("kendoGrid");
//Getting grid items
var items = vgrid.dataSource.data();
alert("length = " + items.length);
alert("Non Outage Cost = " + ($('#NonOutageCostInput').val()));
for (i = 0; i < items.length; i++) {
var item = items[i];
if ($('#NonOutageCostInput').val() > 0) {
item.NonOutageCost = $('#NonOutageCostInput').val();
}
}
//Refresh will change the row values - but the dirty flag isn't set - so the Save Changes doesn't update the database
//alert("before refresh");
//$("#grid").data("kendoGrid").refresh();
}
11 Answers, 1 is accepted
When you change values manually in the dataSource, those change are not made in the Grid itself, so the dirty indication for the cell with the changed value will not be added automatically. When you use the set method you will have to manually add the dirty indicator class to the TD element, right after you change the value:
.k-dirty-cell
If other questions arise, please do not hesitate to contact us again.
Regards,
Konstantin Dikov
Telerik by Progress
Could you show me how to change the TD element? I'm spinning through the items in the datasource. I just don't know how to then get to the TD element. Below is my javascript code. I've spent many hours trying to figure this out - but no luck. It would be great if you could show me how to get to the TD element from where I change the values in the datasource. Thanks.
function myFunction() {
alert("Function executes when button is clicked");
var vgrid = $("#grid").data("kendoGrid");
var rows = vgrid.tbody.children();
var columns = vgrid.columns;
//Getting grid items
var items = vgrid.dataSource.data();
for (i = 0; i < items.length; i++) {
var item = items[i];
if ($('#NonOutageCostInput').val() > 0) {
item.set("NonOutageCost", $('#NonOutageCostInput').val());
}
//I tried this and it didn't work - can you show me how to get to the TD Element
var row = $(rows[i]);
var cell = row.children().eq(4);
cell.addClass("k-dirty-cell");
$('<span class="k-dirty"/>').prependTo(cell);
}
}
Following is a dojo example demonstrating such implementation:
Hope this helps.
Regards,
Konstantin Dikov
Telerik by Progress
Konstantin - thank you. That is exactly what I was looking for. It appears you wrote the solution you showed me specifically for me. I really appreciate that.
I do have one question that I don't understand. You have a for loop for the data. And another for loop for the dirty flag. How come those loops have to be separate? I tried to combine the two for loops into one loop. But when I did that - the dirty flag didn't change. Unless I clicked on the button a second time. So I have 2 for loops like your example. This doesn't make sense to me. Do you know why it works this way?
You need to ensure that all changes to the dataSource are applied, before moving to the dirty flags, because on each change the Grid will be rendered again. Another thing to have in mind is that the first loop is going trough all items in the dataSource, but the second loop is traversing the items on the current page only.
Best Regards,
Konstantin Dikov
Telerik by Progress
I have another question about this. How do I look at individual cell values in the grid?
My use case is to click a button that executes a JavaScript function. The JavaScript function spins through the grid and changes data. Konstantin showed me how to do this and it works. So now I want to expand the use case. Instead of just updating all of the rows in the grid. I want to look a another column in the grid to determine if I should update the grid.
Konstantin showed me how to set the datasource value and the grid value. I have to have 2 loops. One loop for datasource, and the other loop for HTML to set the dirty flag. But as I'm spinning through the grid, how do I look at the contents of another cell?
The command to update a cell in the datasource is this: items[i].set("SpringCost", $('#SpringCostInput').val()); I'm struggling how to evaluate the contents of another column. I tried items[I].getElementByID("SelectionField"), but that didn't work.
The command to update a cell in the HTML is: $(rows[i].cells[4]).addClass("k-dirty-cell"); How would I look at the contents of a column called "SelectionField" in this loop?
Nevermind - got this working now. Here's what I did. If anyone sees a better way then please let me know.
In the datasource - the way to look at an individual field is: items[i].YourFieldName
In the HTML grid data - the way to look at an individual field is: $(rows[i].cells[9]).text()
While the data is updated on all pages, as soon as you to go the next page you lose the dirty indicator.
Also, another question:
What if I just want to set the values and dirty flag on the current page?
I tried the below code, but because the grid may have been sorted this won't work. Is there a way to go from a grid.item to the corresponding grid.datasource.data?
function onDefaultSelect() {
var combobox = $("#defaultStatus").data("kendoComboBox");
var selected = combobox.value()
if (selected == "Reviewed - Release to Vendor") {
kendo.ui.progress($("#Grid"), true);
setTimeout(function () {
var grid = $("#Grid").data("kendoGrid");
//get current page
var page = grid.dataSource.page();
//get page size
var pageSize = grid.dataSource.pageSize();
var items = grid.dataSource.data();
//get index range of items to default
var startRange = (page == 1) ? 0 : ((page - 1) * pageSize);
var endRange = page * pageSize;
if (endRange > items.length) {
endRange = items.length;
}
//default items in range
for (var i = startRange; i < endRange; i++) {
items[i].set("ImageStatusId", 2);
}
//default items
var rows = grid.items();
startRange = 0;
endRange = pageSize;
if (endRange > rows.length) {
endRange = rows.length;
}
for (var i = startRange; i < endRange; i++) {
$(rows[i].cells[2]).addClass("k-dirty-cell");
$(rows[i].cells[2]).append("<span class='k-dirty'></span>");
}
combobox.select(0);
}, 20);
setTimeout(function () {
kendo.ui.progress($("#Grid"), false);
}, 20);
}
}
A better way to say this is:
For the current grid page, how do I set the value and dirty indicator in javascript?
If you want to get reference to the corresponding dataItem from a TR element, you could use the "dataItem" method of the Grid:
Additionally, if you use the "view" method of the DataSource, it will return the items on the current page and then you could use the "set" method to change the values. Note that with the latest version, using the "set" method will add the dirty indicator in the cells as well.
Best Regards,
Konstantin Dikov
Progress Telerik