Persist the State of the Grid alongside the Function Handlers
Environment
Product | Progress® Kendo UI® Grid for jQuery |
Description
By default, the JSON.stringify()
method cannot serialize function definitions. Event handlers and other similar Grid configurations are lost when the state of the component is persisted with getOptions
and setOptions
.
How can I persist the state of the Data Grid and include the function definitions in the saved options?
Solution
To achieve the desired scenario, implement a custom JSON reviver
parameter, which can serialize and deserialize the function definitions.
<script type="x-kendo/template" id="template">
<button class='k-button' onclick='kendo.alert("WORKS")'>My Button</button>
</script>
<button id="save">Save Options</button>
<button id="set">Set Options</button>
<div id="grid"></div>
<script>
extendJsonParsing();
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
},
schema: {
model: {
fields: {
OrderID: { type: "number" },
Freight: { type: "number" },
ShipName: { type: "string" },
OrderDate: { type: "date" },
ShipCity: { type: "string" }
}
}
},
pageSize: 20,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
// A dataBound function that must also be saved in the options of the user.
dataBound: function (e) {
console.log("The DataBound event was fired.");
},
toolbar: kendo.template($("#template").html()),
height: 550,
filterable: true,
sortable: true,
pageable: true,
columns: [{
field: "OrderID",
filterable: false
},
/* An editable function that must also be saved in the options of the user. */
{ field: "Freight", editable: function () { return false; } },
{
field: "OrderDate",
title: "Order Date",
format: "{0:MM/dd/yyyy}"
}, {
field: "ShipName",
title: "Ship Name"
}, {
field: "ShipCity",
title: "Ship City"
}
]
});
});
$("#save").on("click", function (e) {
e.preventDefault();
var options = $("#grid").data("kendoGrid").getOptions();
// Stringify the Grid options.
var stringOptions = JSON.stringify(options);
// Save them in the local storage.
localStorage["kendo-grid-persist-options"] = stringOptions;
});
$("#set").on("click", function (e) {
e.preventDefault();
var options = localStorage["kendo-grid-persist-options"];
if (options) {
// Parse the options by using the custom reviver.
var parseOptions = JSON.parse(options, Function.deserialize);
var grid = $("#grid").data("kendoGrid");
// Set the options back to the Grid.
grid.setOptions(parseOptions);
}
});
function extendJsonParsing() {
Function.prototype.toJSON = function () {
// Retrieve the function definition.
var output = this.toString();
// The default schema.model.fields parsers cannot be serialized. You need to exclude them.
var parsers = ["number", "date", "boolean", "string"];
if (
this.name &&
(new RegExp('^\\s*' + this.name + '\\s*([(])')).test(output)
)
output = 'function ' + output;
// Stringify the function as long as it isn't one of the default parsers.
if (!parsers.includes(this.name))
return Function.prototype.toJSON.flag + output;
};
Function.prototype.toJSON.flag = '_FUNC';
Function.deserialize = function (key, data) {
// Check if the current field that is being deserialized is a function or not.
if (!Function.deserialize.check.test(data))
return data;
// If it is a function, remove the flag from it.
data = data.replace(Function.deserialize.check, '');
// Parse the string back to a regular function.
return new Function(
'return (' + data + ').apply(this, arguments);'
);
};
Function.deserialize.check = new RegExp('^' + Function.prototype.toJSON.flag);
}
</script>