Skip to main content Skip to footer

Customizing Wijgrid with Persistent State

DESCRIPTION

Wijgrid supports different kinds of customizations and it could vary from user to user. In this blog article we will cover one such user scenario and extend wijgrids functionality. One of the nice features of wijgrid is the ability to customize the control, from a developer standpoint and from an end user standpoint The end user can sort, page, and organize the data in a way that suits their individual needs, however whenever the end user leaves the page, all of their configurations that they made are lost. I would like to cover how we can take user customizations and save them in a cookie on the users machine so when the user returns the page, they will see all of their customizations unchanged and ultimately saving your end users lots of time. In addition to showing you how to save cookies that contain relevant data to the grids customizations, I also intrudoce Require.js. Require.js is a nice tool that addresses many problems that developers are having these days as websites are becoming more “app-like” and complex. By using Require.js we have the ability to load nested dependencies, while also not worrying about order of laods, and adds some ease of use for the developer but then is backed with an optimization tool that helps development and scalability for your application.

IMPLEMENTATION

The sample provided below contains all of the CDNs that can be found in our quick start so I will brush over that part. Basically, an overview of the sample is, we have a table that we turn into a Wijgrid using Wijmo’s Jquery scripts. The wijgrid will use Require.js to load the necessary dependencies. The state of the grid will be stored in a cookie on the users machine. Let’s go ahead and dive directly into building the grid. Inside the body tags of your HTML page add the following markup:


<table id="demo">  
</table>  

This code should look very familiar as we are simply defining and assigning an ID to a table in the markup. Below is the require.js code that belongs inside your ( not to be mistaken with the thing that sits on your shoulders ) tags.


<script type="text/javascript" src="http://cdn.wijmo.com/external/require.js"></script>  
<script type="text/javascript">  
requirejs.config({  
baseUrl: "http://cdn.wijmo.com/amd-js/",  
paths: {  
"jquery": "jquery-1.9.1.min",  
"jquery-ui": "jquery-ui-1.10.1.custom.min",  
"jquery.ui": "jquery-ui",  
"jquery.mousewheel": "jquery.mousewheel.min",  
"globalize": "globalize.min",  
"bootstrap": "bootstrap.min", //Needed if you use Bootstrap.  
"knockout": "knockout-2.2.0", //Needed if you use Knockout.  
"cookie": "jquery.cookie"  
}  
});  
</script>  

The following code will transform you table with id=”demo” into the wijgrid that we all know and love. There are some comments in the function that I have added so later in the blog it is clear where to put the code.


require(["wijmo.wijgrid", "jquery.cookie"], function () {  
$(document).ready(function () {  
// insert if statement here  
$("#demo").wijgrid({  
allowSorting: true,  
allowColMoving: true,  
selectionMode: "singleRange",  
data: getData(10),  
columnsAutogenerationMode: "none",  
columns: [  
{ dataKey: "ProductName", headerText: "Product Name", dataType: "string" },  
{ dataKey: "UnitPrice", headerText: "Unit Price", dataType: "currency" },  
{ dataKey: "Quantity", headerText: "Quantity", dataType: "number", dataFormatString: "n0" },  
{ dataKey: "Discount", headerText: "Discount", dataType: "number", dataFormatString: "p0" },  
{ dataKey: "OrderDate", headerText: "Order Date", dataType: "datetime", dataFormatString: "MMM-dd-yyyy"},  
{ dataKey: "Overseas", headerText: "Overseas", dataType: "boolean" }  
]  
});  
// more code will go in here  
}  
// savestate() functions  

// end if statement here.  

This code is almost complete but we need to add the getData function to our application. I will glaze over this because how we get the data isn’t important to the idea of the blog but I have included some sample data for your convenience. You can put these functions at the end of your scripts


// random data generators  
function getData(count) {  
var data = [];  
var name = "Lorem,Ipsum,Dolor,Amet,Consectetur,Adipiscing,Elit,Vivamus,Pharetra,Velit,Eget,Imperdiet,Mattis,Egestas,Donec,Tempus,Vestibulum,Tincidunt,Blandit,Lacinia,Lobortis,Feugiat,Mauris,Massa,Rutrum,Pulvinar,Ornare,Facilisi,Sociis,Natoque,Penatibus".split(",");  
var suffix = "LLC,Inc,International,Transpacific,Services,Financial,Enterprises,Consultants,Foundation,Institute".split(",");  
for (var i = 0; i < count; i++) {  
data.push({  
TransactionID: i,  
ProductName: getString(name) + " " + getString(suffix),  
UnitPrice: getNumber(10, 100),  
Quantity: Math.floor(getNumber(1, 500)),  
Discount: getNumber(0, 0.3),  
OrderDate: getDate(i),  
Overseas: Math.random() > 0.8  
});  
}  
return data;  
}  
function getString(arr) {  
return arr[Math.floor((Math.random() * arr.length))];  
}  
function getNumber(lo, hi) {  
return lo + Math.random() * (hi - lo);  
}  
function getDate(daysAgo) {  
return new Date((new Date()).getTime() - daysAgo * 24 * 3600 * 1000);  
}  

Now, we need to create two functions that get and set our cookies. For our saveState() function, we need to create an array to hold the state of the grid and a few other variables. Once we have created these, we loop through and assign them, and finally we build our cookie properties, use JSON to stringify it and then store it as a cookie.


// save/restore grid state  
function saveState() {  
var state = {};  
//array for column options  
var headerText = new Array();// column properties  
var dataType = new Array();// column properties  
var dataKey = new Array();// column properties  
var dataFormatString = new Array();// column properties  
// save sort state  
var cols = $("#demo").wijgrid("option", "columns"); // column properties  
// for loop to cycle through the array  
for (var i = 0; i < cols.length; i++) {  
headerText.push(cols[i].headerText);  
dataType.push(cols[i].dataType);  
dataKey.push(cols[i].dataKey);  
if(cols[i].dataFormatString != undefined)  
{  
//value set for dataFormatString  
dataFormatString.push(cols[i].dataFormatString)  
}  
else  
{  
//undefined is default value for dataFormatString  
dataFormatString.push(undefined)  
}  
if (cols[i].sortDirection && cols[i].sortDirection != "none") {  
state.sortColumn = cols[i].dataKey;  
state.sortDirection = cols[i].sortDirection;  
}  
}  
//add column options to state object  
state.headerText = headerText;  
state.dataType = dataType;  
state.dataKey = dataKey;  
state.dataFormatString = dataFormatString;  
// save selection state  
var sel = $("#demo").wijgrid("selection").selectedCells();  
state.selStart = getCellAddress(sel.item(0));  
state.selEnd = getCellAddress(sel.item(sel.length() - 1));  

// persist state in cookie (could also use localStorage or sessionStorage)  
var string = JSON.stringify(state);  
$.cookie('gridState', string);  
}  
For our restore function, it is virtually the same only the order is backwards.  
function restoreState() {  
var state = $.cookie("gridState");  
if (state) {  
state = JSON.parse(state);  
var newColumns = new Array();  
for(i = 0; i < state.dataKey.length; i++)  
{  
//check if dataFormatString is set  
if(state.dataFormatString[i] != undefined)  
{  
newColumns.push({'dataKey':state.dataKey[i], 'headerText':state.headerText[i], 'dataType':state.dataType[i], 'dataFormatString':state.dataFormatString[i]});  
}  
else  
{  
newColumns.push({'dataKey':state.dataKey[i], 'headerText':state.headerText[i], 'dataType':state.dataType[i]});  
}  
}  

// create grid with columns and options from previous session  
$("#demo").wijgrid({  
allowSorting: true,  
allowColMoving: true,  
selectionMode: "singleRange",  
data: getData(10),  
columnsAutogenerationMode: "none",  
columns: newColumns  
});  

$("#demo").wijgrid({  
columnDropped: function (e, args) {  
saveState();  
}  
});  
$("#demo").wijgrid({  
sorted: function (e, args) {  
saveState();  
}  
});  
$("#demo").wijgrid({  
selectionChanged: function (e, args) {  
saveState();  
}  
});  
if (state.sortColumn && state.sortDirection) {  
var cols = $("#demo").wijgrid("columns");  
for (var i = 0; i < cols.length; i++) {  
if (cols[i].options.dataKey == state.sortColumn) {  
cols[i].element.c1field("option", "sortDirection", state.sortDirection);  
break;  
}  
}  
}  

// restore selection (using timeOut to allow the sort to be applied first)  
setTimeout(function () {  
if (state.selStart && state.selEnd) {  
var sel = $("#demo").wijgrid("selection");  
sel.beginUpdate();  
sel.clear();  
var c1 = state.selStart.split(",");  
var c2 = state.selEnd.split(",");  
sel.addRange(c1[1], c1[0], c2[1], c2[0]);  
sel.endUpdate();  
}  
}, 0);  
}  
}  

function getCellAddress(cell) {  
return cell.rowIndex() + "," + cell.cellIndex();  
}  

Once we have created these helper functions, we then need to go back to our original wijgrid builder function ( this was the first script we added ). I have copied the function and highlighted things to add in red for your convenience.


require(["wijmo.wijgrid", "jquery.cookie"], function () {  
$(document).ready(function () {  
//if cookie isn't set create new grid  
if($.cookie("gridState") == null)  
{  
$("#demo").wijgrid({  
allowSorting: true,  
allowColMoving: true,  
selectionMode: "singleRange",  
data: getData(10),  
columnsAutogenerationMode: "none",  
columns: [  
{ dataKey: "ProductName", headerText: "Product Name", dataType: "string" },  
{ dataKey: "UnitPrice", headerText: "Unit Price", dataType: "currency" },  
{ dataKey: "Quantity", headerText: "Quantity", dataType: "number", dataFormatString: "n0" },  
{ dataKey: "Discount", headerText: "Discount", dataType: "number", dataFormatString: "p0" },  
{ dataKey: "OrderDate", headerText: "Order Date", dataType: "datetime", dataFormatString: "MMM-dd-yyyy"},  
{ dataKey: "Overseas", headerText: "Overseas", dataType: "boolean" }  
]  
});  
//save state on colum reorder, any sort event, and any cell selection change  
$("#demo").wijgrid({  
columnDropped: function (e, args) {  
saveState();  
}  
});  
$("#demo").wijgrid({  
sorted: function (e, args) {  
saveState();  
}  
});  
$("#demo").wijgrid({  
selectionChanged: function (e, args) {  
saveState();  
}  
});  
}  
//if cookie is set restore state from cookie  
else  
{  
// restore state saved in the last session  
restoreState();  
}  
});  
});  

If any of these instructions are unclear, I have provided a sample that you can run on your own machine. Note that your cookie will not appear in chromes cookies list, if you are running your website locally. DOWNLOAD SAMPLE

MESCIUS inc.

comments powered by Disqus