Is there a way to prevent the collapse on setting the master row dataItem? This seems like bad default behaviour.
Also: I can't seem to expand it again:
var
parentRow = $(input).closest(
'.k-detail-row'
).prev(
'.k-master-row'
)[0];
var
parentGrid = $(parentRow).closest(
'div.k-grid'
).data(
"kendoGrid"
);
var
parentDataItem = parentGrid.dataItem($(parentRow).closest(
'tr'
));
parentDataItem.set(
"QTY"
, newParent.QTY);
parentGrid.expandRow(parentRow);
17 Answers, 1 is accepted
Calling set method of the ObservableObject will trigger change event that will bubble up to the DataSource and the Grid will repaint in order to show the changes.
That said the reference to the row you keep (in the code snippet) is to the old DOM element before the refresh. This is why the expand does not work - as the element is no longer in the DOM tree.
To workaround you can keep the index of the item before calling set and before calling expand to get DOM element for that index.
Nikolay Rusev
Telerik
I have a grid where the detail expansion is being used as an edit view for the row, so that multiple rows can be expanded and compared/edited simultaneously.
However, as detailed above, when I save the changes back to the server and then attempt to update the local dataItem (since detail views are not bound to the viewmodel, I have to manually update the client side data), *all* detail views collapse despite only one rows' data being updated at a time. It makes sense that the row being edited should collapse as the user is finished with their changes to that row, but the entire grid is being redrawn when any data change is made.
Is there any way to prevent this?
This behavior is fundamental for how the Grid widget works and there aren't any changes. You can control this behavior by not updating the data item directly on every change from the UI, but rather on click of some global save button.
Regards,
Nikolay Rusev
Telerik
Each row and it's detail expansion is treated as it's own entity, and is managed individually. The changes are saved on a per-row basis. The issue here is that the dataSource is triggering the grid to refresh/read all data instead of the row that was modified.
This is counter-intuitive. You can edit/add/delete/template/select/expand a row but you can't update a row. You can only update the data source.
In this link, Editable fields in grid details you can find more information about editing the dataItem fields of a grid in detailRow with no success. When you update the originalModel of a row, the grid collapses all the expanded detailRows and this makes losing the data entered by the user in other detailRows.
Alexander told me that "this is by desing".
Hope this helps.
Oscar.
Quite simply, when you have as much data to display as I do (64 data points by my last count), the built in edit modes are insufficient. We supply an "at a glance" view of the most useful data points in the grid itself and use the detail expansion to provide a form-like editor where multiple rows can be expanded at once.
Using inline or batch would just be insane. No one is going to deal with a 64 column grid.
Popup would be OK if we could popup multiple rows for comparison/copying, but it still wouldn't solve the issue that I am having saving data on a per-row basis and losing the work on other expanded rows that may or may not actually need to be saved.
In such scenarios you basically have two options:
- e.preventDefault() inside grid dataBinding handler - this will prevent grid repaint
or
- collect expanded rows indices on dataBinding event, and expand them back on dataBound event.
Regards,
Nikolay Rusev
Telerik
We are getting somewhere now. The e.preventDefault sounds promising.
If we can prevent the grid repaint, I should only need two more things to get to my intended behavior.
1. A way to detect what triggered the dataBind event so I can differentiate a dataSource read from a local data update. This would let filtering/paging/sorting through properly, but stop it from happening when I'm refreshing the data on my own.
2. A way to refresh the front end grid cells manually.
You can assert against the `action` argument what action has happened. For example `itemchange` will be triggered when you modify model field via set method.
dataBinding:
function
(e) {
if
(e.action ==
"itemchange"
) {
console.log(e.items);
}
}
Regards,
Nikolay Rusev
Telerik
Here is the source code for my grid's dataBinding handler:
dataBinding:
function
(e) {
if
(e.action ==
"itemchange"
) {
e.preventDefault();
var
item = e.items[0];
//get the current column names, in their current order
var
grid = $(
'#'
+ currentViewModel.gridId).data(
'kendoGrid'
);
var
columns = grid.columns;
var
columnNames = $.map(columns,
function
(column) {
return
column.field;
});
//get the column tds for update
var
masterRow = $(
'#'
+ currentViewModel.gridId +
' > div.k-grid-content > table > tbody > tr[data-uid="'
+ item.uid +
'"]'
);
var
tds = masterRow.find(
'td:not(.k-hierarchy-cell)'
);
//collapse the detail row that was saved.
grid.collapseRow(masterRow);
//update the tds with the value from the current item stored in items
for
(
var
i = 0 ; i < tds.length ; i++) {
$(tds[i]).html(item[columnNames[i]]);
}
}
}
It's not perfect, but the general idea is to get the current state of the columns, since I have column customizations enabled, find the master row tds by using the uid of the items[0] object, then set the tds value to the items current state.
I also collapse the row here, but this isn't necessary, and would actually work better for the OP.
I still need to run certain columns through formatters and templates, but that's small potatoes compared to getting this far.
http://docs.telerik.com/kendo-ui/api/web/grid#events-dataBinding
These two fields were instrumental in getting a workable solution. They really should be added there for others' future reference.
We will definitely update the docs in order to address the missing parts.
We are also open for contribution on our documentation portal. You can find more details here: Update the Documentation at GitHub.
Regards,
Nikolay Rusev
Telerik
If I use e.preventDefault(), then the grid does not repaint, which is good. However, I'm encountering a problem using these series of steps (on a two level grid - a master grid and a detail grid):
1. Expand master grid
2. Edit an item in the child grid (works well - the grid does not repaint)
3. Change the filter on the dataSource, while will cause the grid to repaint (as expected)
4. After the repaint, try to expand the master grid again <--- PROBLEM IS HERE
Basically, when doing Step 4, the grid will "expand", but in reality it will just show an empty child grid container. The child grid will not actually render. I've narrowed this down to being caused by using e.preventDefault() on the dataBinding event. This ONLY happens when repainting the grid (such as by filtering, as above) after editing a cell. In addition, if after the filtering, I edit one of the master rows, and THEN expand the master grid, then it works. Or, I can also try to expand a different master row after the initial failure, and this will work too.
So, the problem is in the FIRST expand event after the dataSource is refreshed and the grid is repainted. Subsequent expansions, or just editing a cell before trying the first expand, fixes the issue. Do you guys have any suggestions as to how to resolve this issue?
Hello Yaron,
e.preventDefault() on dataBinding event will not render any data in the Grid. This is expected. However I'm not sure about implementation. Thus I'll suggest you opening separate forum thread/support ticket and attach some example of your implementation.
Regards,
Nikolay Rusev
Telerik
I have also had similar problems with nested grids when using the checkbox-column solution proposed by Telerik (http://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/Templates/grid-with-checkbox-column).
I solved it by triggering a click on the "edit-cell's" checkbox instead of using dataItem.set():
01.
$(
"#grid .k-grid-content"
).on(
"change"
,
"input.chkbx"
,
function
(e) {
02.
// Get the parent grid of the checkbox. This can either be the master grid or the detail grid.
03.
var
parentGrid = $(e.target).closest(
'div[data-role="grid"]'
).data(
"kendoGrid"
);
04.
// Get the clicked cell.
05.
var
td = $(e.target).closest(
"td"
);
06.
// Enter the cell's edit mode.
07.
parentGrid.editCell(td);
08.
// Find the checkbox in the cell (which now is in "edit-mode").
09.
var
checkbox = td.children(
"input[type=checkbox]"
);
10.
// Trigger a click (which will toggle check/uncheck).
11.
checkbox.trigger(
"click"
);
12.
});