I have a Kendo grid which Displays data based on filter criteria in TextBox above clicking search button. The grid has edit and Detail Action links which take user to a different view (no popup or inline), loading more fields than we Display in grid for edit.When done editing and user Comes back to grid it must retain old filter criteria, selected record, page etc. Which is the best way to achieve this using Kendo grid?
Anamika
24 Answers, 1 is accepted
This code library project shows a sample implementation: http://www.telerik.com/support/code-library/save-grid-state-in-session-on-server-side
Regards,
Atanas Korchev
Telerik
Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.
This is a good sample, but my Scenario is different. the grid has a Action link button in each row clicking which takes user to a different Controller showing Details from selected row . When back clicked we should come back to Display grid with old search criteria and old selected page and record. So i cannot have a load button to click and load the saved state, it should be invoked automatically after read Action i believe
The project shows how to persists only the grid sate - page, sort, filter and grouping. You would need to save and restore any other page state separately. You can persist the grid state automatically by handling the dataBound event of the grid:
@(Html.Kendo().Grid<
TelerikMvcApp1.Models.Product
>()
.Name("grid")
.DataSource(ds => ds.Ajax().Read("Read", "Home"))
.Events(e => e.DataBound("grid_dataBound"))
.Pageable()
.Groupable()
.Sortable()
.Reorderable(r => r.Columns(true))
.Resizable(r => r.Columns(true))
)
<
script
>
function grid_dataBound() {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
var state = {
columns: grid.columns,
page: dataSource.page(),
pageSize: dataSource.pageSize(),
sort: dataSource.sort(),
filter: dataSource.filter(),
group: dataSource.group()
};
$.ajax({
url: "/Home/Save",
data: {
data: JSON.stringify(state)
}
});
}
</
script
>
You can restore the grid state when the page is loaded:
<
script
>
$(document).ready(function() {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
$.ajax({
url: "/Home/Load",
success: function(state) {
state = JSON.parse(state);
var options = grid.options;
options.columns = state.columns;
options.dataSource.page = state.page;
options.dataSource.pageSize = state.pageSize;
options.dataSource.sort = state.sort;
options.dataSource.filter = state.filter;
options.dataSource.group = state.group;
grid.destroy();
$("#grid")
.empty()
.kendoGrid(options);
}
});
});
</
script
>
I couldn't reproduce the problem you are observing. Please check this video which shows my experience - the 6th page is successfully restored after clicking the Load state button.
Regards,
Atanas Korchev
Telerik
Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.
$("#save").click(function() {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
var state = {
page: dataSource.page(),
pageSize: dataSource.pageSize()
};
$.ajax({
url: "/Home/Save",
data: {
data: JSON.stringify(state)
}
});
});
$("#load").click(function() {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
$.ajax({
url: "/Home/Load",
success: function(state) {
state = JSON.parse(state);
var options = grid.options;
options.dataSource.page = state.page;
options.dataSource.pageSize = state.pageSize;
grid.destroy();
// grid.dataSource.query(state);
$("#grid")
.empty()
.kendoGrid(options);
}
});
});
$("#save").click(function() {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
var state = {
page: dataSource.page(),
pageSize: dataSource.pageSize(),
sort: dataSource.sort(),
filter: dataSource.filter(),
group: dataSource.group()
};
$.ajax({
url: "/Home/Save",
data: {
data: JSON.stringify(state)
}
});
});
$("#load").click(function() {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
$.ajax({
url: "/Home/Load",
success: function(state) {
state = JSON.parse(state);
var options = grid.options;
options.dataSource.page = state.page;
options.dataSource.pageSize = state.pageSize;
options.dataSource.sort = state.sort;
options.dataSource.filter = state.filter;
options.dataSource.group = state.group;
grid.destroy();
// grid.dataSource.query(state);
$("#grid")
.empty()
.kendoGrid(options);
}
});
});
</script>
The column state should be persisted as expected. I recorded another video which shows the same.
Could you please tell us the browser and operating system that you are using?
Regards,
Atanas Korchev
Telerik
Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.
Kendo UI doesn't support Safari on Windows. This browser hasn't been updated by Apple since 2012. We however fully support Safari on OSX.
I tested the sample project on IE10 and it still works. Do you see any JavaScript errors when you click the load and save state buttons?
Regards,
Atanas Korchev
Telerik
Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.
This is very strange because this sample has been tested by many users on various browsers and operating systems. There seems to be something unique about your setup which we haven't encountered so far. I recommend checking with the browser debugger whether the $.ajax call is made when you click the "save state" button. If the browser successfully executes $.ajax then it should make a request to the action method. If it doesn't execute that code then there must be some runtime error preventing this.
Regards,
Atanas Korchev
Telerik
Build cross-platform mobile apps using Visual Studio and .NET. Register for the online webinar on 03/27/2014, 11:00AM US ET.. Seats are limited.
I wanted to reply to this since I had such a tough time getting it all working. I'm using an MVC grid with Ajax binding. Here is what I used to make it work. This way doesn't need the controller calls either, all just localstorage, and less code, so a combination of above and what I found on another topic.
@section Scripts {
<
script
>
$(document).ready(function () {
var grid = $("#grid").data("kendoGrid");
var options = localStorage["kendo-grid-options"];
if (options) {
grid.setOptions(JSON.parse(options));
}
});
function grid_dataBound() {
var grid = $("#grid").data("kendoGrid");
localStorage["kendo-grid-options"] = kendo.stringify(grid.getOptions());
}
</
script
>
}
For those trying to get grid persistence to work across sessions, browsers, and computers, here is the solution. My project uses Kendo MVC Grid, but this JavaScript applies to any use of the Kendo Grid. One of the keys is to ensure your grids have Autobind set to false, otherwise you get grids loading 2x on a page and create a chicken/egg scenario.
The following is true
1) All grids set AutoBind(false)
2) document.ready looks for any grids on page and then calls the getGridPersistence method
3) getGridPersistence reads the database and retrieves the persistence based on UserID/URL/GridID
4) getGridPersistence then sets the grid by first destroying it, then providing the destroyed grid the persistence options in the getGridPersistenceOnSuccess method.
5) if a user makes any changes to the grid, I have events listening on dataBound and various column events that will then call the setGridPersistence method. The setGridPersistence calls getOptions() and saves out only the items I want to the db.
CODE:
001.
//Called whenever model data and UI needs to be synchronized
002.
window.X.GGrid.onDataBound =
function
(e) {
003.
var
gridId = e.sender.wrapper.context.id;
004.
005.
if
(gridId !=
null
) {
006.
// Grid.AutoBind(false) must be set for this to work properly. Other code in document.ready will fire
007.
// off the databind when window.X.GGrid.getGridPersistence is called. This also has the wanted side effect of only loading
008.
// the grid 1x upon page load.
009.
setGridPersistence(e);
010.
011.
// If an active filter is set, change the css class to show a filter icon
012.
var
jqGridId = $(
"#"
+ gridId);
013.
014.
015.
// Since our grids are using the menu widget and not the default grid header, normal filter icons and operations
016.
// are different. This code manually cycles through the filtered columns and applies the correct class
017.
// that will apply the filter icon when the filter is set
018.
var
grid = jqGridId.data(
"kendoGrid"
);
019.
var
filter = grid.dataSource.filter();
020.
021.
if
(filter) {
022.
grid.thead.find(
".k-header-column-menu.k-state-active"
).removeClass(
"k-state-active"
);
023.
var
filteredMembers = {};
024.
setFilteredMembers(filter, filteredMembers);
025.
}
026.
027.
this
.thead.find(
"th[data-field]"
).each(
function
() {
028.
var
cell = $(
this
);
029.
var
filtered =
null
;
030.
if
(filter) {
031.
filtered = filteredMembers[cell.data(
"field"
)];
032.
}
033.
034.
if
(filtered !=
null
) {
035.
cell.find(
".k-header-column-menu"
).addClass(
"k-state-active"
);
036.
cell.find(
".k-icon"
).removeClass(
"k-i-arrowhead-s"
).addClass(
"k-filter"
);
037.
}
038.
else
{
039.
cell.find(
".k-icon"
).removeClass(
"k-filter"
).addClass(
"k-i-arrowhead-s"
);
040.
}
041.
});
042.
043.
}
044.
}
045.
046.
// Method to tell the UI that a column is filtered.
047.
// Called from the onDataBound event code.
048.
function
setFilteredMembers(filter, members) {
049.
if
(filter.filters) {
050.
for
(
var
i = 0; i < filter.filters.length; i++) {
051.
setFilteredMembers(filter.filters[i], members);
052.
}
053.
}
054.
else
{
055.
members[filter.field] =
true
;
056.
}
057.
}
058.
059.
// Get's the grids persistence from the database and configures the grid appropriately
060.
window.X.GGrid.getGridPersistence =
function
(e, gridId) {
061.
if
((e !=
null
) || (gridId !=
null
)) {
062.
063.
// if gridId is passed in use it, otherwise get gridId from button custom attribute
064.
if
(gridId ==
null
) {
065.
gridId = e.target.attributes[
'gridId'
].nodeValue;
066.
}
067.
068.
var
relativeUrl = $(location).attr(
'pathname'
);
069.
070.
$.ajax({
071.
url:
"/common/gridpersistence/GetGridPersistence"
,
072.
type:
"POST"
,
073.
data: JSON.stringify({
'gridId'
: gridId,
'relativeUrl'
: relativeUrl }),
074.
contentType:
"application/json"
,
075.
success:
function
(data)
076.
{
077.
getGridPersistenceOnSuccess(data, gridId);
078.
},
079.
error:
function
() {
080.
alert(
"An error has occured while getting Grid Persistence View!!!"
);
081.
}
082.
});
083.
}
084.
}
085.
086.
// Seperated out of AJAX call to debug and follow process
087.
// This method can only ever get called if there is a grid on the page.
088.
function
getGridPersistenceOnSuccess(state, gridId) {
089.
var
grid = $(
"#"
+ gridId).data(
"kendoGrid"
);
090.
091.
// save the toolbar
092.
var
toolBar = $(
"#"
+ gridId +
" .k-grid-toolbar"
).html();
093.
094.
if
(state !=
null
&& state !==
''
) {
095.
// set options that were retreived
096.
//grid.setOptions(JSON.parse(data));
097.
state = JSON.parse(state);
098.
var
options = grid.options;
099.
100.
options.columns = state.columns;
101.
options.dataSource.page = state.page;
102.
options.dataSource.pageSize = state.pageSize;
103.
options.dataSource.sort = state.sort;
104.
options.dataSource.filter = state.filter;
105.
options.dataSource.group = state.group;
106.
options.dataSource.aggregate = state.aggregate;
107.
108.
// destroy current grid
109.
grid.destroy();
110.
111.
// set options into empty grid in DOM
112.
var
gridThatWasReset = $(
"#"
+ gridId);
113.
gridThatWasReset
114.
.empty()
115.
.kendoGrid(options);
116.
117.
// force a data read
118.
grid = gridThatWasReset.data(
"kendoGrid"
);
119.
grid.dataSource.read();
120.
121.
// reset the toolbar
122.
var
toolBarSelector = $(
"#"
+ gridId +
" .k-grid-toolbar"
);
123.
toolBarSelector.html(toolBar);
124.
toolBarSelector.addClass(
"k-grid-top"
);
125.
}
126.
else
{
127.
// just perform a read without resetting toolbar buttons when it's the first time viewing a grid
128.
grid.dataSource.read();
129.
}
130.
}
131.
132.
// Saves the grids current configuration into the database
133.
function
setGridPersistence(e) {
134.
if
(e !=
null
) {
135.
var
gridId =
null
;
136.
137.
if
(e.target ==
null
)
138.
{
139.
// if coming from grid event
140.
gridId = e.sender.wrapper.context.id;
141.
}
142.
else
143.
{
144.
// If coming from button click
145.
gridId = e.target.attributes[
'gridId'
].nodeValue;
146.
}
147.
148.
var
grid = $(
"#"
+ gridId).data(
"kendoGrid"
);
149.
var
dataSource = grid.dataSource;
150.
var
relativeUrl = $(location).attr(
'pathname'
);
151.
152.
// Set specific options
153.
var
state = {
154.
columns: grid.columns,
155.
page: dataSource.page(),
156.
pageSize: dataSource.pageSize(),
157.
sort: dataSource.sort(),
158.
filter: dataSource.filter(),
159.
group: dataSource.group(),
160.
aggregate: dataSource.aggregate()
161.
};
162.
163.
164.
var
options = JSON.stringify(state);
165.
//var options = kendo.stringify(grid.getOptions());
166.
167.
$.ajax({
168.
url:
"/common/gridpersistence/SetGridPersistence"
,
169.
type:
"POST"
,
170.
data: JSON.stringify({
'gridId'
: gridId,
'relativeUrl'
: relativeUrl,
'options'
: options }),
171.
contentType:
"application/json"
,
172.
success:
function
(data) {
173.
// alert('saved persistence');
174.
175.
},
176.
error:
function
() {
177.
alert(
"An error has occured while saving Grid Persistence View!!!"
);
178.
}
179.
});
180.
}
181.
};
182.
183.
// Resets the grids configuration by deleting persistence info from the database, then refreshing the entire page.
184.
function
resetGridPersistence(e) {
185.
if
(e !==
null
&& e !== undefined) {
186.
var
gridId = e.target.attributes[
'gridId'
].nodeValue;
187.
var
grid = $(
"#"
+ gridId).data(
"kendoGrid"
);
188.
var
relativeUrl = $(location).attr(
'pathname'
);
189.
190.
if
(
typeof
grid !==
"undefined"
) {
191.
$.ajax({
192.
url:
"/common/gridpersistence/ResetGridPersistence"
,
193.
type:
"POST"
,
194.
data: JSON.stringify({
'gridId'
: gridId,
'relativeUrl'
: relativeUrl }),
195.
contentType:
"application/json"
,
196.
success:
function
(data) {
197.
198.
if
(data) {
199.
// only way to refresh the column widths is to reload page as other methods like data.read() don't do the trick
200.
location.reload();
201.
}
202.
},
203.
error:
function
() {
204.
alert(
"An error has occured while resetting Grid Persistence View!!!"
);
205.
}
206.
});
207.
208.
209.
}
210.
}
211.
};
212.
213.
214.
$(document).ready(
function
() {
215.
// Find all grids in a page
216.
var
grids = $(
"div"
).find(
".k-grid"
);
217.
218.
if
(grids !=
null
&& grids.length > 0) {
219.
grids.each(
function
() {
220.
var
gridId =
this
.id;
221.
if
(gridId !==
''
) {
222.
//fetch persistence settings for each grid
223.
window.X.GGrid.getGridPersistence(
null
, gridId);
224.
}
225.
});
226.
}
Thank you for sharing your solution with the community.
As a gesture of gratitude you will find your Telerik Points updated.
Kind Regards,
Konstantin Dikov
Telerik by Progress
The server-side code should contain the relevant part for saving the state in the database and having in mind that you need to save grid id, the URL and the options (as string), there should be nothing special about it.
Nevertheless, the following forum thread should be helpful for retrieving the values in the controller:
Best Regards,
Konstantin Dikov
Telerik by Progress
Hello Atanas
I have the same problem like Anamika, when i include columns it is not working else its working fine. on further debug in chrome developer tools, i found something if i include columns, data is not passed as string to controller. If i remove columns it works fine data is passed as string.
Please find attached image.
Most probably you are exceeding the max length of the query string when you include the columns structure. You could take a look at the following thread for a solution:
Regards,
Konstantin Dikov
Telerik by Progress
Hello Dikov
Thanks for your quick response.
It didn't work adding max requests to web config.
neither this <httpRuntime maxQueryStringLength="32768" maxUrlLength="65536"/> nor this
<system.webServer><security><requestFiltering><requestLimits maxQueryString="32768"/></requestFiltering></security></system.webServer> or both didnt work
Thanks
Raj
Could you please try setting higher values to the httpRuntime maxQueryStringLength and if the request fails again, click on the request and inspect the "Preview" tag to see what is the thrown error. Another option is to change the type of the request to "post":
$.ajax({
type: "post",
Regards,
Konstantin Dikov
Telerik by Progress
We get and set grid options the same. We allow our users to save different grid setups with names though instead of saving through events. My question have you or anyone else tried to update the json stored in the database when you make changes to the grid schema? Like adding or removing columns and/or attributes. We don't want to to have to reset the stored grid options and make our users recreate them all.
Since I have access to the database, I use a PowerShell script to update the json but it's not robust enough to handle all scenarios.
Theoretically, there should be a way to retrieve the JSON, convert (parse) it to an object (either client-side or server-side), make the desired changes and then stringify and save it back. All this can happen outside of the Kendo UI context and without using our APIs. As long as the modified object can be used by the Kendo UI as a valid configuration object, this approach should work.
Regards,
Dimo
Telerik by Progress