jqGrid and ASP.NET MVC - Configuration Import/Export
Today I'm going to write few words about configuration import and export in jqGrid. This feature can be very helpful, if you wish to allow your users with some customization (in our example we will add column chooser, so users can influence what they see).
We should start by adding standard placeholders for the grid:
Before we start writing our actions, we have to prepare a model binder for JSON, otherwise we won't be able to accept configuration:
Finally, we can write controller actions. Data will be provided by the action written in basics sample, so I will focus on actions which import and export configuration:
We should start by adding standard placeholders for the grid:
<table id="jqgProducts" cellpadding="0" cellspacing="0"></table>Now we will write all necessary javascript:
<div id="jqgpProducts"></div>
<link href="../../Content/jquery-ui-1.7.2.custom.css" rel="stylesheet" type="text/css" />That's a lot of javascript. I hope that comments make it clear enough. We are exporting in JSON but also XML can be used as an alternative. There is also a possibility to import some data with configuration, but I won't dig into this at the moment.
<link href="../../Content/ui.jqgrid.css" rel="stylesheet" type="text/css" />
<link href="../../Content/ui.multiselect.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/grid.locale-en.js" type="text/javascript"></script>
<script src="/Scripts/jquery.jqGrid.min.js" type="text/javascript"></script>
<script src="/Scripts/ui.multiselect.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
//Calling jqGridImport, which will import configuration
$('#jqgProducts').jqGridImport({
//We are expecting data in JSON format
imptype: 'json',
//URL to our action, which will return configuration
impurl: '<%=Url.Action("ProductsGridConfiguration", "Home") %>',
//Method for the request
mtype: 'GET',
//Addidtional data, which will be passed to our action
impData: { id: 'jqgProducts' },
//We inform the grid which property in object will hold configuration
jsonGrid: { config: 'Settings' },
//Function which will be called when import ends
importComplete: function() {
//We set up navigator wihout any standard buttons
$('#jqgProducts').jqGrid('navGrid', '#jqgpProducts', {
edit: false,
add: false,
del: false,
search: false
//because we will add our own button
}).jqGrid('navButtonAdd', '#jqgpProducts', {
//Our button text
caption: 'Columns',
//Our button icon (jQuery UI class)
buttonicon: 'ui-icon-wrench',
//Our button position
position: 'last',
//Our button tooltip
title: 'Select columns',
//Function which will be called on click
onClickButton: function() {
//We are showing column chooser
$('#jqgProducts').jqGrid('columnChooser', {
//Function which will be called when column chooser is closed
done: function(perm) {
//We check if user has accepted
if (perm) {
//First we are resizing grid
var gridWidth = this.jqGrid('getGridParam', 'width');
this.jqGrid('setGridWidth', gridWidth);
//then we remap columns
this.jqGrid('remapColumns', perm, true);
//and in the end we want to post configuration
$.ajax({
type: 'POST',
//We are posting configuration in JSON
contentType: 'application/json; charset=utf-8',
//URL to our action, which store configuration
url: '<%=Url.Action("ProductsGridConfiguration", "Home") %>',
//Calling jqGridExport for our data
data: $('#jqgProducts').jqGridExport({
//We are exporting in JSON
exptype: 'jsonstring',
//We inform the grid what should be the name of property
root: 'Settings'
})
});
}
}
});
}
});
}
});
});
</script>
Before we start writing our actions, we have to prepare a model binder for JSON, otherwise we won't be able to accept configuration:
/// <summary>Now we can prepare classes for storing jqGrid configuration:
/// Model binder which allows binding JSON data to objects
/// </summary>
public class JsonModelBinder : IModelBinder
{
#region IModelBinder Members
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (bindingContext == null)
throw new ArgumentNullException("bindingContext");
var serializer = new DataContractJsonSerializer(bindingContext.ModelType);
return serializer.ReadObject(controllerContext.HttpContext.Request.InputStream);
}
#endregion
}
/// <summary>As you can see, I have skipped most of JqGridSettings and JqGridColumnModel implementation. Those classes contain only properties which represent jqGrid options.
/// jqGrid configuration container
/// It can have two properties:
/// - one for settings
/// - one for data
/// </summary>
[DataContract]
[ModelBinder(typeof(JsonModelBinder))]
public sealed class JqGridConfiguration
{
#region Properties
[DataMember]
public JqGridSettings Settings { get; set; }
#endregion
}
/// <summary>
/// jqGrid settings container
/// Description for every option is available here:
/// http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options
/// Not all jqGrid options are included in this class (it can be extended)
/// </summary>
[DataContract]
public sealed class JqGridSettings
{
#region Properties
[DataMember]
public JqGridColumnModel[] colModel { get; set; }
...
#endregion
...
}
/// <summary>
/// jqGrid colModel options
/// Description for every option:
/// http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options
/// Not all jqGrid colModel options are included in this class (it can be extended)
/// </summary>
[DataContract]
public sealed class JqGridColumnModel
{
...
}
Finally, we can write controller actions. Data will be provided by the action written in basics sample, so I will focus on actions which import and export configuration:
/// <summary>Now we can go ahead and test it. You can download sample application from here, I hope you will find it useful.
/// Exports configuration for jqGrid in json
/// </summary>
/// <param name="id">The jqGrid identifier</param>
/// <returns>The jqGrid configuration in json format</returns>
[NoCache]
public JsonResult ProductsGridConfiguration(string id)
{
JqGridConfiguration configuration = null;
//Do we already have configuration in Session
if (Session[id] != null)
//If yes, the use it
configuration = (JqGridConfiguration)Session[id];
else
//If no, then create one
configuration = new JqGridConfiguration()
{
Settings = new JqGridSettings
{
id = id,
colNames = new string[] { "ProductID", "ProductName", "Supplier", "Category", "QuantityPerUnit", "UnitPrice", "UnitsInStock" },
colModel = new JqGridColumnModel[]
{
new JqGridColumnModel() { name = "ProductID", align = "left" },
new JqGridColumnModel() { name = "ProductName", align = "left" },
new JqGridColumnModel() { name = "Supplier", align = "left" },
new JqGridColumnModel() { name = "Category", align = "left" },
new JqGridColumnModel() { name = "QuantityPerUnit", align = "left" },
new JqGridColumnModel() { name = "UnitPrice", align = "left" },
new JqGridColumnModel() { name = "UnitsInStock", align = "left" }
},
remapColumns = new int[] { 0, 1, 2, 3, 4, 5, 6 },
rowNum = 10,
sortname = "ProductID",
sortorder = "asc",
viewrecords = true
}
};
//Those settings should be set always "just in case"
configuration.Settings.url = Url.Action("ProductsGridData", "Home");
configuration.Settings.datatype = "json";
configuration.Settings.mtype = "GET";
configuration.Settings.pager = "#jqgpProducts";
configuration.Settings.width = "auto";
configuration.Settings.height = "auto";
//Return configuration
return Json(configuration);
}
/// <summary>
/// Imports configuration for jqGrid
/// </summary>
/// <param name="configuration">The jqGrid configuration</param>
/// <returns>An empty result</returns>
[AcceptVerbs(HttpVerbs.Post)]
public EmptyResult ProductsGridConfiguration(JqGridConfiguration configuration)
{
//Store configuration in Session
Session[configuration.Settings.id] = configuration;
//Return empty result, it will be ignored
return new EmptyResult();
}