I have a page where one grid has to have the possibility to add/remove rows on the client before saving all the changes to the server.
The grid is created like this
@(Html.Kendo().Grid(Model.AssignedObjects)
.Name("AssignedGrid")
.Columns(columns =>
{
columns.Select().Width(35);
columns.Bound(p => p.Description);
})
.Pageable(p => p.PageSizes(true)
.ButtonCount(5))
.Sortable()
.Scrollable()
.HtmlAttributes(new { style = "height: 450px;" })
.DataSource(dataSource => dataSource.Ajax()
.ServerOperation(false)))
The remove is done using the below javascript code
function
removeSelected() {
var
grid = $(
'#AssignedGrid'
).data(
'kendoGrid'
);
var
dataSource = grid.dataSource;
var
rows = grid.select();
var
data = rows.map(
function
() {
return
grid.dataItem($(
this
));
});
for
(
var
i = 0; i < data.length; i++) {
dataSource.remove(data[i]);
}
grid.clearSelection();
}
On the remove function I had also had a code to go to the first page ( dataSource.page(1) ) but if I remove all the data going to page 1 would display the initial data. Now without the code to go to the first page it works by going to page 0 and displaying no items.
However I still have a problem when I change the number of records on a page I get again to the first page and the initial data. Is there a way to really remove the data, so regardless what actions I do (), not to get the initial data?
10 Answers, 1 is accepted
Thank you very much for the provided code snippet.
I would suggest using the selectedKeyNames() method instead, whereas the select() method only returns the current page. This distinction seems to be lacking from the documentation and I shall see to add it there so no one stumbles upon it in the future. Here is my suggested modification for the custom code which removes selected items:
var
dataSource = grid.dataSource;
var
selected = grid.selectedKeyNames();
$.each(selected,
function
(idx, key){
var
item = grid.dataSource.get(key);
grid.dataSource.remove(item);
});
grid.dataSource.page(1);
Here is a runnable Dojo that I tested with for your reference:
https://dojo.telerik.com/@bubblemaster/AhURAzOX
Let me know what you think and if you need further assistance, please do not hesitate to ask.
Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Hi Alex,
Unfortunally that dojo you provided is not really the same situation as the MVC. I tried to make also a dojo when I placed the question but ended in the same situation as the one that I tried now to change your dojo (the data is not displayed in the grid).
So I updated your dojo to emulate what MVC produces by having the datasource transport do not do anything on read and added the data option setting to be the sampleData. Also on the grid I updated the pageable to have 3 options
however just like my first atempt to create a dojo the grid is loaded with nothing displayed in it just an empty row
https://dojo.telerik.com/avUSUduD.
If you manage to make it work here is the workflow that I need:
delete all the rows from the only one page (so all the rows have to fit in one page)
the grid should go to page 0 (by calling grid.dataSource.page(1) would load the initial data so it might need to comment it to get to the page 0)
change the number of item on the page (so my problem here is that when I do this the initial data is displayed even though I removed them)
Thank you for your feedback. Indeed there was a difference in the behaviour of the Kendo UI Grid. So I went ahead and prepared a test project which I believe behaves as you wish. Since this is a forum thread, I removed the Kendo.Mvc.dll but you may add it in the lib folder to run the project.
I made a little change in the Grid definition - I added the model id as well as set "PersistSelection(true)":
@(Html.Kendo().Grid(Model)
.Name(
"AssignedGrid"
)
.ToolBar(t=>t.Custom().Name(
"RemoveSelected"
).IconClass(
"k-icon k-i-trash"
))
.Columns(columns =>
{
columns.Select().Width(50);
columns.Bound(p => p.ShipName);
})
.Pageable(p => p.PageSizes(
true
)
.ButtonCount(5))
.Sortable()
.Scrollable()
.PersistSelection(
true
)
.HtmlAttributes(
new
{ style =
"height: 450px;"
})
.DataSource(dataSource => dataSource.Ajax()
.Batch(
true
)
.Model(m=>m.Id(
"OrderID"
))
.ServerOperation(
false
))
)
The handler of the toolbar custom command now uses the grid API - removeRow() method instead of the dataSource
$(
".k-grid-RemoveSelected"
).on(
"click"
,
function
(e) {
e.preventDefault()
var
grid = $(
"#AssignedGrid"
).data(
"kendoGrid"
)
var
dataSource = grid.dataSource;
var
selected = grid.select();
$.each(selected,
function
(idx, row) {
grid.removeRow(row);
});
grid.dataSource.page(1);
});
Let me know if this is the desired outcome when you get the chance to test my suggestion.
Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Hi Alex,
I manage to get to test your solution in my application and found that what I was missing and it was the most important part of this work is the line: .Model(m=>m.Id("OrderID")) . So you have to give an Id to the datasource in order for the removable to be permanent.
The definition of a schema model id is crucial for the data source to work correctly.
https://docs.telerik.com/kendo-ui/controls/data-management/grid/editing#define-fields-through-schema
The note is in the Kendo UI documentation, do you think we should add that in the MVC documentation as well, perhaps in all of the below articles or in another article for local data operations? Would you mind letting me know if you looked through them? In your opinion, what is the best place to add a note so that it is more visible?
https://docs.telerik.com/aspnet-mvc/helpers/grid/editing/batch-editing
https://docs.telerik.com/aspnet-mvc/helpers/grid/editing/ajax-editing
https://docs.telerik.com/aspnet-mvc/helpers/grid/editing/server-editing
Look forward to hearing back from you.
Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Hi Alex,
Honestly I did not know that the Model was crucial for datasource to work. Usually I add the model only when I want something special for the fields, like default value or if not editable. Also I had no problem not adding it to a grid just for viewing
As for the 3 links I don't think I have seen them before (or if I did I did not pay too much attention). Usually I look at the demos or search the web for similar situations and I get the kendo-ui version that I try to adapt to MVC
Thank you for your feedback. I will add a note to our backlog so that the requirement to have an "id" for editing is more visible. On a side note, the persistSelection property also requires the schema model id to be defined.
Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Hi Alex,
Please be aware that sometimes the Model.Id function throws an exception.
So I have the following configuration
@(Html.Kendo().DropDownListFor(m => m.DeviceDesignation)
.DataTextField("Name")
.DataValueField("Id")
.HtmlAttributes(new
{
@class = "form-control s-devicedesignation",
data_valuemapperurl = Url.Action("GetDeviceDesignationsValueMapper", "Common")
})
.Filter(FilterType.Contains)
.OptionLabel(Localizer.GetString("Select a designation...").ToString())
.DataSource(source => source.Ajax()
.PageSize(50)
.Read(read => read.Action("GetDeviceDesignations", "Common"))
.Model(m => m.Id("Id"))
.Events(events => events.Error("deviceclass.dataSourceError")))
.Virtual(v => v.ValueMapper("deviceclass.deviceClassDesignationValueMapper"))
.Deferred()
and I got this exception
System.NullReferenceException: Object reference not set to an instance of an object.
at Kendo.Mvc.UI.Fluent.DataSourceModelDescriptorFactoryBase`1.Id(String fieldName)
at AspNetCore._Views_DeviceClass_Edit_cshtml.<>c.<ExecuteAsync>b__19_4(DataSourceModelDescriptorFactory`1 m) in ...\Edit.cshtml:line 29
at Kendo.Mvc.UI.Fluent.AjaxDataSourceBuilderBase`2.Model(Action`1 configurator)
The line 29 is the one with .Model(m => m.Id("Id"))
So it seems that not all the time the Model has to be defined.
The schema model id is necessary for:
- grid editing to work correctly
- grid persistSelection to work correctly
- the dataSource get() method to work correctly
I suppose that the data in the provided snippet does not always have an Id field, hence the error?
In case this error is thrown during a Grid Create operation with a complex field, a default value for the DeviceDesignation model type should be provided in the grid data source definition. Let's say that the DeviceDesignation property is a DeviceDesignationViewModel class instance with two properties - Id and Name:
model.Field(p => p.DeviceDesignation).DefaultValue(
new
DeviceDesignationViewModel(){ Id =
"abc"
, Name =
"SomeName"
});
The data source schema id of the dropdown data source is not necessary.
For a complete example, you may check the demo at:
https://demos.telerik.com/aspnet-mvc/grid/editing-custom
Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Hi Alex,
The dropdown was use outside of a grid and the data always had an Id for the returned values.
Also I assumed that the Model is necessary for the DataSource regardless of where it is used (Grid, DropDownList, TreeList, ListBox, etc...)
But you cleared my confusion that only in case of grid the Model is necessary.