There is no any built in way to store
entire grid state into database and restore back again with all
filters, groups, aggregates, page and page size.
At first, I was trying to restore only
filters by looking through DataSourceRequest. DataSourceRequest is
kind of communication medium between client and server for the
operation we do on grid. All the request comes via DataSourceRequest.
In previous approach, I was trying to store IFileDescriptor interface
which come with class FileDescriptor by looping through filters and
serializing into string for saving into database but this
IFileDescriptor can also contain CompositeFilterDescriptor which can
be nested in nested object which are very tricky to handle.
So, I had decompiled entire Kendo.MVC
library and found out that all Kendo MVC controls are derived from
“JsonObject”. It is there own implementation with ”Serialize”
abstract function and “ToJson” function. In controls they are
overriding “Serialize” method which depicts the object found on
JavaScript for Kendo control. The “ToJson” function is returning
“IDictionary<string,object>”. This is all we need. We can
transform “IDictionary<string,object>” from “ToJson”
and store into database and on initialization of grid on client side
we can put these values directly on Kendo Grid.
Please note that serialization/direct
storing could have been done directly on JavaScript level but there
is no event associated to filters and might be same with other as
well.
Let's start by defining Kendo MVC Grid
control but we will not populate grid data right away while
rendering. We got to initialize settings first (grid state from DB)
and then populate data and restore grid state through “DataSource”.
To stop grid data population Kendo MVC helper has “AutoBind()”
function which can be set as “AutoBind(false)” .
Here is the entire grid sample:
@(Html.Kendo().Grid<ViewModel>()
.Name("GridSample")
.Columns(columns =>
{
columns.Bound(vm => vm.LastName);
columns.Bound( vm => vm.FirstName);
columns.Bound( vm => vm.MiddleName);
columns.Bound( vm => vm.Id).Title("Id #");
})
.AutoBind(false)
.DataSource(datasource => datasource
.Ajax()
.Read(read => read.Action("GetAllData", "SampleGrid", new { area = "" })
)
.PageSize(20)
)
.Reorderable(reorder => reorder.Columns(true))
.Pageable()
.Filterable()
.Sortable()
.ColumnMenu()
.Scrollable()
.Selectable(selectable => selectable.Mode(GridSelectionMode.Single)))
// JavaScript call
<script type=”text/javascript”>
RestoreGridSetting("GridSample")
</script>
After setting up grid we need to
initialize grid with data stored into DB through JavaScript.
function RestoreGridSetting (gridId) {
if (gridId === undefined || gridId === null) {
return;
}
// Select row
var grid = $('#' + gridId).data('kendoGrid');
if (grid === undefined) {
return;
}
// Initialize columns
$.get('/api/userprofilegrid/' + gridId.toLowerCase(), function (data) {
if (data === undefined || data === null) {
return;
}
// Set values from result of WebAPI call
grid.dataSource.filter(JSON.parse(data.Filters));
grid.dataSource.sort(JSON.parse(data.Sorts));
grid.dataSource.group(JSON.parse(data.Groups));
grid.dataSource.aggregate(JSON.parse(data.Aggregates));
});
}
If the first request comes it will get
information from WebApi and restore on grid via grid's datasource.
Now, let's look into action request which will be called from Grid control.
.Read(read => read.Action("GetAllData", "SampleGrid", new { area = "" })
Everything will remain as it is (DataSourceRequest) just that we need to save data into database which would be resulted by WebAPI call from JavaScript. So, here is server side code for GetAllData.
var gridDetail = // TODO: Get object from DB;
if (gridDetail == null)
{
return;
}
gridDetail.Aggregates = JsonConvert.SerializeObject(request.Aggregates.OfType<JsonObject>().ToJson());
gridDetail.Filters = JsonConvert.SerializeObject(request.Filters.OfType<JsonObject>().ToJson());
gridDetail.Groups = JsonConvert.SerializeObject(request.Groups.OfType<JsonObject>().ToJson());
gridDetail.PageSize = request.PageSize;
gridDetail.Sorts = JsonConvert.SerializeObject(request.Sorts.OfType<JsonObject>().ToJson());
//gridDetail.PageLocation = request.Page;
// TODO: Save object
The above function is using
Newtonsoft.JSON library to parse data from
“IDictionary<string,object>” which is generated form
“ToJson” call.
To summarize all of them as steps
1. Create grid control by setting
“Autobind” as false.
2. Through AJAX call get grid state
model and set the value into grid's datasource.
3. On server side grid's action to
retrieve data, save DataSourceRequest properties with the help
of “ToJson” and "JsonCovert".
NOTE: In this article, I have not
covered restoring hidden columns and column grid position. There are
plenty of resource that can be followed to achieve it.
Comments
Post a Comment