Click here to Skip to main content
12,557,148 members (31,400 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


74 bookmarked

jqGrid MVC Html Helper

, 14 Nov 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
MVC 3 jqGrid HTML Helper.


JQGRID HTML helper is a sever side code wrapper that generates javascript for jqGrid used by MVC 3 applications. The HTML helper provides all the jqGrid features such ajax json data binding, jsonp, editing, filtering, and customization.

JQGRID plugin is a full feature open source html grid control. Using jqGrid in MVC application is a little tidious manual hand coding. HTML helper simply this process and provide a consistent interface.


JQGRID html helper provides an easy consistent way to render JQGRID JAVASCRIPT that constructs a grid in the web page. The helper is specifically designed for MVC 3 web page. The data binding is any data type defined by JQGRID documentation. It is preferable to use JSON data type and AJAX back to the controller to retrieve the data. During document ready, the html helper created java script function will retrieve JSON data and render the grid content. The html help automatically creates 2 <DIV> elements on the page, one for the grid and the other one is for the pager. The JSON data should contain metadata information to properly render the grid with paging capability.

jQGRID HTML supports subgrid, custom subgrid and custom tree grid. Subgrid is a recursive method that render the a grid within the parent grid. A custom subgrid when expanded, a partial view is retrieved from the controller. A custom tree grid also retrieves partial views including the final level.

Using the code

In the view, create the basic grid by adding the HTML helper namespace, and then add the grid control, add the columns, set the ajax URL call and create the controller method.

@using Mvc.HtmlHelpers
    // columns
    .addColumn(new Column("AccountNumber").setLabel("AccountNumber").setWidth(100).setSortable(true))
    .addColumn(new Column("AccountName").setLabel("AccountName").setWidth(250).setSortable(true).setEditable(true))
    .addColumn(new Column("AccountDate").setLabel("Date").setWidth(70).setSortable(true))
    .addColumn(new Column("AccountType").setLabel("Type").setWidth(80).setSortable(true))
    .addColumn(new Column("AccountBalance").setLabel("Balance").setWidth(80).setSortable(true))
    // settings
    .setRowList(new int[]{10,15,20,50})
    // render the html

Create the view with ajax callback URL to the controller. The JSON result contains metadata such as total number of pages (total), current page (page), total number of records (records) ans rows (data content).

public ActionResult GetAccountList(GridSettings gridSettings)
    // retrieve the sorted data
    List<Models.Account> accounts = Models.Account.GetAccounts();

    // create json data
    int pageIndex = gridSettings.pageIndex;
    int pageSize = gridSettings.pageSize;
    int totalRecords = accounts.Count;
    int totalPages = (int)Math.Ceiling((float)totalRecords / (float)pageSize);

    int startRow = (pageIndex - 1) * pageSize;
    int endRow = startRow + pageSize;

    var jsonData = new
        total = totalPages,
        page = pageIndex,
        records = totalRecords,
        rows =
            from Models.Account a in accounts
            where a.Row >= startRow && a.Row <= endRow
            select new
                id = a.AccountNumber,
                cell = new string[] 

    return Json(jsonData, JsonRequestBehavior.AllowGet);

Custom subgrid is a grid with a subgrid that has callback to the controller to retrieve partial view.

@using Mvc.HtmlHelpers
    // columns
        .addColumn(new Column("AccountNumber").setLabel("AccountNumber").setWidth(100).setSortable(true))
        .addColumn(new Column("AccountName").setLabel("AccountName").setWidth(250).setSortable(true).setEditable(true))
        .addColumn(new Column("AccountDate").setLabel("Date").setWidth(70).setSortable(true))
        .addColumn(new Column("AccountType").setLabel("Type").setWidth(80).setSortable(true))
        .addColumn(new Column("AccountBalance").setLabel("Balance").setWidth(80).setSortable(true).setAlign(Align.right))
    // settings
    .setRowList(new int[] { 20, 50, 100, 200, 300 })
    // error handler
    .onLoadError("Error loading Account List")
    // events
        var grid = $('#CustomGridAccount');
        grid.jqGrid('setLabel', 'AccountBalance', '', {'text-align':'right'});
     // subgrid
        new jqGrid("CustomGridDetails")
        .onLoadError("CustomGrid Account Details")
        .setSubGridOptions("{plusicon : 'ui-icon-circle-plus', minusicon : 'ui-icon-circle-minus'}")
    // render the html
Custom subgrid detail is just a partial view with <tr> and <td> only, the html return from the controller is appended to the parent <tr>
@using jqGrid.Sample.Models
@model List<AccountDetail>
    Layout = null;  
@foreach (AccountDetail detail in Model)
    <tr class="subGridRow">

Custom tree has three parts, the main grid, the level subgrid, and the detail level grid. These are all partial views.

@using Mvc.HtmlHelpers
    // columns
    .addColumn(new Column("Name").setLabel("Organization").setWidth(350))
    .addColumn(new Column("AssetAllocation").setLabel("Asset Allocation"))
    .addColumn(new Column("ClientReview").setLabel("Client Review"))
    .addColumn(new Column("IneligibleActivity").setLabel("Ineligible Activity"))
    .addColumn(new Column("InvestmentGuideline").setLabel("Investment Guideline"))
    .addColumn(new Column("BillableAssets").setLabel("Billable Assets"))
    .addColumn(new Column("NonEarnedPcs").setLabel("Non-Earned PCs"))
    // settings
        new jqGrid("CustomTreeLevel")
        .setSubGridOptions("{plusicon : 'ui-icon-plus', minusicon : 'ui-icon-minus', openicon:'ui-icon-carat-1-sw'}")
    // render grid
<script type="text/javascript">
    function toggleExpCol(elementId, row_id) {
        var iconElement = $('#' + elementId);
        if (iconElement.hasClass('ui-icon-plus')) {
                type: 'get',
                contentType: 'application/json; charset=utf-8',
                url: "@Url.Content("~/Home/CustomTreeLevel?rowId=")" + row_id + '',
                success: function (data, textStatus) {
                    var newTr = $(data);
                    $(newTr).each(function (i) {
                        $(this).attr('isExpanded', false);
                        $(this).attr('parent', row_id);
                    $($('#CustomTree tr#' + row_id)).attr('isExpanded', true);
                    $($('#CustomTree tr#' + row_id)).after(newTr);
        else {
            var grid = $("#CustomTree").jqGrid();
            var getChildrenNode = function (row_id) {
                var result = [];
                var children = $(grid).find('tr[parent=' + row_id + ']');
                $(children).each(function (i) {
                    if ($(this).attr("isExpanded") == "true") {
                        var chl = getChildrenNode(;
                        $(chl).each(function (i) {
                return result;
            var childern = getChildrenNode(row_id);
            $.each(childern, function (index, value) { $(value).remove(); });

Custom tree level a partial view controlled with parent ID attribute. The onclick function is on the main view that toggle expand and collapse.

@using Mvc.HtmlHelpers
@using jqGrid.Sample.Models
@model List<Organization>
    Layout = null;
    string rowId = (string)ViewData["RowId"];
    int level = Convert.ToInt32(rowId.Split('_')[0]) + 1;
    int width = (int)(12 * level * 1.5);
    int left = width - 18;
@foreach (Organization org in Model)
    <tr id="@(org.Id)" class="ui-widget-content" role="row">

 Updated: GridSettings.cs 

using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace Mvc.HtmlHelpers
    public enum OPERATION

    public class GridSettings
        public int pageIndex { get; set; }
        public int pageSize { get; set; }
        public string sortColumn { get; set; }
        public string sortOrder { get; set; }
        public bool isSearch { get; set; }
        public string id { get; set; }
        public string param { get; set; }
        public string editOper { get; set; }
        public string addOper { get; set; }
        public string delOper { get; set; }
        public Filter where { get; set; }
        public OPERATION operation { get; set; }

    public class GridModelBinder : IModelBinder

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            HttpRequestBase request = controllerContext.HttpContext.Request;
            return new GridSettings()
                isSearch = bool.Parse(request["_search"] ?? "false"),
                pageIndex = int.Parse(request["page"] ?? "1"),
                pageSize = int.Parse(request["rows"] ?? "10"),
                sortColumn = request["sidx"] ?? "",
                sortOrder = request["sord"] ?? "asc",
                id = request["id"] ?? "",
                param = request["oper"] ?? "",
                editOper = request["edit"] ?? "",
                addOper = request["add"] ?? "",
                delOper = request["del"] ?? "",
                where = Filter.Create(request["filters"] ?? ""),
                operation = (OPERATION)System.Enum.Parse(typeof(OPERATION), request["oper"] ?? "none")


    public class Filter
        public string groupOp { get; set; }
        public Rule[] rules { get; set; }

        public static Filter Create(string jsonData)
                var serializer = new DataContractJsonSerializer(typeof(Filter));
                System.IO.StringReader reader = new System.IO.StringReader(jsonData);
                System.IO.MemoryStream ms = new System.IO.MemoryStream(Encoding.Default.GetBytes(jsonData));
                return serializer.ReadObject(ms) as Filter;
                return null;

    public class Rule
        public string field { get; set; }
        public string op { get; set; }
        public string data { get; set; }

To support (CUD) Add, Edit, and Delete, Grid setting is updated to handle operations such as add, edit, del and other operations. On the view, there are methods such 


Set navigation methods (.setNav) is to enable add,edit and delete buttons on the paging row.  Controller get a callback for saving CUD when the row is edited. Use grid settings operation to check which task to for add, edit or del operations. 

public void SaveGridUpdate(GridSettings gridSettings)
    string id =;
        case OPERATION.add:
            // do create
        case OPERATION.edit:
            // do update
        case OPERATION.del:
            // do delete
} is the row id that was modified, there is also a way to retrieve all the updated fields from the Request object. Do set a debug break point on the save callback method to determine how to retrieve these fields. 

Points of Interest
jqgrid wiki has plenty of documentation for all the options available.

The HTML helper contains most used features however not all features are implemented here. You are welcome to extend this helper.

Fixes by Richard

  1. Fixed a bug with the "datefmt" setter logic (the string value was originally “datafmt”).
  2. Added methods for "cellEdit" and "cellsubmit" for selective editing of cell data.
  3. Added select, textbox, datetime, and checkbox grid fields to the sample project for performing data updating in the grid. There are now fields for each of those data types in the grid and all of those fields are editable.
  4. Added submit/post logic for returning edited data to the server via a button added to the “_Grid” page.
  5. Added alternate row zebra striping.
  6. Re-enabled the Site.css file for a better look and feel.
  7. Changed the modeling around to better represent the way that data would be created – (i.e., from back-end controller functionality), as well as adding additional hidden fields to the model that are passed back and forth.
  8. Downloaded the latest version of jqGrid (4.4.1) and implemented it in the project in an unsuccessful attempt to solve the problem discussed below.
  9. Everything works nicely, except there is a serious problem with the cell editing functionality, which I am currently researching. Here are the specifics:

    If you click an editable cell, it will enter edit mode, and the cell contents can be changed. However, if you then click on another cell and fail to press the enter key first (whether you have made changes to the cell contents or not), the cell contents are cleared. The original value then cannot be restored and new values cannot be entered. It is even worse on a checkbox field. If you are on any line except the first one in the grid, this problem will happen regardless of what you do.

    Furthermore, when the submit process to the server is launched by clicking the button, the contents of the hidden field used to contain the json grid data is screwed up after it is set by the JS button logic, and will contain html markup data (including “<” characters), causing ASP.Net to barf and display an “unsafe data submission” error page.

    It seems ridiculous to me that the enter key needs to be pressed after making a change, or even before leaving an editable field. This looks like a jqGrid bug. Please check it out and let me know if I did anything wrong.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ken C. Len
Software Developer (Senior) LEN Associates Inc.
United States United States
Years of software consulting and software development using Microsoft development products such as Microsoft Content Management System, SQL Server Reporting Service, ASP.Net C# VB.Net, HTML and javascript web development, Visual Studio add-on development, C++ MFC/ATL and COM+ development, and ActiveX components.

You may also be interested in...

Comments and Discussions

BugSpecial characters in filter toolbar Pin
Gustavo Parra17-Oct-14 7:08
memberGustavo Parra17-Oct-14 7:08 
Questionjqgrid print Pin
pranayabsingh9-May-14 4:03
memberpranayabsingh9-May-14 4:03 
QuestionHow do i post back additional data? Pin
Member 1958102-Oct-13 8:05
memberMember 1958102-Oct-13 8:05 
QuestionjqGrid Paging feature and TreeGrid Pin
Sergio Arcidiacono3-Jun-13 22:13
memberSergio Arcidiacono3-Jun-13 22:13 
QuestionMultiselect Pin
Member 940577810-May-13 7:39
memberMember 940577810-May-13 7:39 
BugHow to chanage path of Link Pin
Farhan Hashmi1-May-13 8:32
memberFarhan Hashmi1-May-13 8:32 
AnswerRe: How to chanage path of Link Pin
Farhan Hashmi3-May-13 2:53
memberFarhan Hashmi3-May-13 2:53 
QuestionHow to export data to excell. Pin
Farhan Hashmi1-May-13 2:44
memberFarhan Hashmi1-May-13 2:44 
QuestionDropdown list problems Pin
Member 969276230-Apr-13 11:13
memberMember 969276230-Apr-13 11:13 
QuestionsubGridRowExpanded not work Pin
Lluthus13-Apr-13 1:18
memberLluthus13-Apr-13 1:18 
AnswerRe: subGridRowExpanded not work Pin
Ken C. Len16-Apr-13 15:10
memberKen C. Len16-Apr-13 15:10 
QuestionFrozen column Pin
dabolo4-Apr-13 16:03
memberdabolo4-Apr-13 16:03 
QuestionNot able to perform the sorting Pin
JayveeJavier13-Mar-13 2:39
memberJayveeJavier13-Mar-13 2:39 
AnswerRe: Not able to perform the sorting Pin
Ken C. Len16-Apr-13 14:55
memberKen C. Len16-Apr-13 14:55 
QuestionHeight 100% Pin
ashnazg29-Jan-13 4:39
memberashnazg29-Jan-13 4:39 
AnswerRe: Height 100% Pin
Ken C. Len16-Apr-13 15:03
memberKen C. Len16-Apr-13 15:03 
QuestionCasing standards Pin
Josh Mouch24-Jan-13 5:46
memberJosh Mouch24-Jan-13 5:46 
AnswerRe: Casing standards Pin
PIEBALDconsult24-Jan-13 6:34
memberPIEBALDconsult24-Jan-13 6:34 
QuestionThank you! Pin
jmfigueroa12-Jan-13 4:01
memberjmfigueroa12-Jan-13 4:01 
QuestionSolve problem with the cell editing functionality Pin
lvl941219-Dec-12 17:23
memberlvl941219-Dec-12 17:23 
QuestionjqGrid MVC Html Helper,How To Export Data To Excel? Pin
yinxw20104-Dec-12 15:23
memberyinxw20104-Dec-12 15:23 
AnswerRe: jqGrid MVC Html Helper,How To Export Data To Excel? Pin
Ken C. Len12-Dec-12 5:55
memberKen C. Len12-Dec-12 5:55 
GeneralRe: jqGrid MVC Html Helper,How To Export Data To Excel? Pin
yinxw201017-Dec-12 15:39
memberyinxw201017-Dec-12 15:39 
QuestionToolbar Icons Pin
Member 75483713-Nov-12 3:57
memberMember 75483713-Nov-12 3:57 
NewsRe: Toolbar Icons Pin
Ken C. Len14-Nov-12 14:25
memberKen C. Len14-Nov-12 14:25 
QuestionDrop down in Grid Column and Add/Edit Record Pin
ineffablep9-Nov-12 6:41
memberineffablep9-Nov-12 6:41 
SuggestionCode for improving helper Pin
Rich Sorensen9-Nov-12 6:04
memberRich Sorensen9-Nov-12 6:04 
GeneralRe: Code for improving helper Pin
Ken C. Len9-Nov-12 6:22
memberKen C. Len9-Nov-12 6:22 
AnswerRe: Code for improving helper Pin
Rich Sorensen9-Nov-12 11:25
memberRich Sorensen9-Nov-12 11:25 
GeneralRe: Code for improving helper Pin
Ken C. Len17-Apr-13 10:28
memberKen C. Len17-Apr-13 10:28 
GeneralRe: Code for improving helper Pin
ineffablep9-Nov-12 6:46
memberineffablep9-Nov-12 6:46 
GeneralRe: Code for improving helper Pin
Rich Sorensen9-Nov-12 11:26
memberRich Sorensen9-Nov-12 11:26 
GeneralRe: Code for improving helper Pin
ineffablep9-Nov-12 22:05
memberineffablep9-Nov-12 22:05 
GeneralRe: Code for improving helper Pin
sharok8911-Nov-12 19:15
membersharok8911-Nov-12 19:15 
GeneralRe: Code for improving helper Pin
samratbabu15-Nov-12 0:03
membersamratbabu15-Nov-12 0:03 
Questioncrud column Pin
Alessandro Degola28-Oct-12 19:31
memberAlessandro Degola28-Oct-12 19:31 
AnswerRe: crud column Pin
Ken C. Len29-Oct-12 3:45
memberKen C. Len29-Oct-12 3:45 
QuestionCRUD Sample Pin
Member 75483723-Oct-12 7:46
memberMember 75483723-Oct-12 7:46 
AnswerRe: CRUD Sample Pin
Ken C. Len24-Oct-12 5:49
memberKen C. Len24-Oct-12 5:49 
GeneralRe: CRUD Sample Pin
samratbabu14-Nov-12 23:32
membersamratbabu14-Nov-12 23:32 
Buggridsettings.where == null Pin
Member 950797513-Oct-12 4:23
memberMember 950797513-Oct-12 4:23 
GeneralRe: gridsettings.where == null Pin
Ken C. Len15-Oct-12 14:41
memberKen C. Len15-Oct-12 14:41 
GeneralRe: gridsettings.where == null Pin
Member 75483723-Oct-12 7:45
memberMember 75483723-Oct-12 7:45 
QuestionNot quite there Pin
Dave Kreskowiak21-Aug-12 2:09
mvpDave Kreskowiak21-Aug-12 2:09 
QuestionMissing Image Pin
Manas Bhardwaj20-Aug-12 21:57
memberManas Bhardwaj20-Aug-12 21:57 
SuggestionCode explanation missing Pin
@amitgajjar20-Aug-12 19:22
member@amitgajjar20-Aug-12 19:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161026.1 | Last Updated 14 Nov 2012
Article Copyright 2012 by Ken C. Len
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid