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.
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.
}