jqGrid and ASP.NET MVC - Formatting

Last time we have set up our first jqGrid. In this post I'm going to take a look at columns formatting.
First let's use predefined formatter. Setting any of predefined formats for column is as simple as adding formatting type and options to colModel definition. In our example we will format UnitPrice as USD. To achieve this, we will set formatting type to currency with following options: decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2 and prefix: '$'.
<script type="text/javascript">
  $(document).ready(function() {
    $('#jqgProducts').jqGrid({
      ...
      colModel: [
                  ...
                  { name: 'UnitPrice', index: 'UnitPrice', align: 'left', formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, prefix: '$'} },
                  ...
                ],
      ...
    });
  });
</script>

Now let's take a look at custom formatter. We will prepare formatting javascript function for UnitsInStock column (instead of displaying numbers we will be displaying flags which color will depend on amount of units). Function receives three parameters: cellvalue - original value for cell, options - array of options passed in colModel, rowObject - object with row data. Return value of our function should be new value for a cell. We also have to set formatting in colModel.
<script type="text/javascript">
  $(document).ready(function() {
    $('#jqgProducts').jqGrid({
      ...
      colModel: [
                  ...
                  { name: 'UnitPrice', index: 'UnitPrice', align: 'left', formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, prefix: '$'} },
                  { name: 'UnitsInStock', index: 'UnitsInStockPrice', align: 'left', formatter: unitsInStockFormatter }
                ],
      ...
    });
  });

  function unitsInStockFormatter(cellvalue, options, rowObject) {
    var cellValueInt = parseInt(cellvalue);
    if (cellValueInt > 10)
      return "<img src='../../Content/images/ui-flag_green.png' alt='" + cellvalue + "' title='" + cellvalue + "' />";
    else if (cellValueInt > 0)
      return "<img src='../../Content/images/ui-flag_blue.png' alt='" + cellvalue + "' title='" + cellvalue + "' />";
    else
      return "<img src='../../Content/images/ui-flag_red.png' alt='" + cellvalue + "' title='" + cellvalue + "' />";
  };
</script>

Let's take it a little bit further. We will format Supplier column so that it will include a link that displays a popup with supplier details. To achieve this we will use jQuery UI Dialog. To do that, we must reference jQuery UI script file.
<head>
  ...
  <script src="/Scripts/jquery-ui-1.7.2.custom.min.js" type="text/javascript">
  </script>
  ...
</head>
In Controller we will prepare method returning supplier details.
/// <summary>
///
Provides json data for supplier popup
/// </summary>
/// <param name="supplierId">
supplier identifier</param>
/// <returns>
json data</returns>
public ActionResult SupplierData(int supplierId)
{
  //Getting supplier from repository
  Supplier supplier = _repository.GetSupplier(supplierId);

  //Preparing anonymous variable with json data
  var supplierData = new
  {
    companyName = supplier.CompanyName,
    address = supplier.Address,
    postalCode = supplier.PostalCode,
    city = supplier.City,
    country = supplier.Country,
    phone = supplier.Phone,
    homePage = supplier.HomePage
  };

  //Returning json data
  return Json(supplierData);
}

We also must add html markup for dialog.
<div id="jqdlgSupplier">
  <span id="sCompanyName"></span><br /><br />
  <span id="sAddress"></span><br />
  <span id="sPostalCode"></span>, <span id="sCity"></span><br />
  <span id="sCountry"></span><br /><br />
  <span id="sPhone"></span><br />
  <span id="sHomePage"></span>
</div>

At the end we will write two new javascript functions (one for cell formatting and one for dialog display) and add some more initialization logic.
<script type="text/javascript">
  $(document).ready(function() {
    $('#jqgProducts').jqGrid({
      ...
      colModel: [
                  ...
                  { name: 'Supplier', index: 'SupplierID', align: 'left', formatter: supplierFormatter },
                  ...
                  { name: 'UnitPrice', index: 'UnitPrice', align: 'left', formatter: 'currency', formatoptions: { decimalSeparator: '.', thousandsSeparator: ',', decimalPlaces: 2, prefix: '$'} },
                  { name: 'UnitsInStock', index: 'UnitsInStockPrice', align: 'left', formatter: unitsInStockFormatter }
                ],
      ...
    });
    $('#jqdlgSupplier').dialog({ autoOpen: false, bgiframe: true, resizable: false, title: 'Supplier' });
  });

  ...

  function supplierFormatter(cellvalue, options, rowObject) {
    return "<a href='' onlick='showSupplierDialog(this, " + cellvalue.substr(1, 1) + "); return false;'>" + cellvalue.substr(4) + "</a>";
  };

  function showSupplierDialog(linkElement, supplierId) {
    //request json data
    $.getJSON('/Home/SupplierData/', { supplierId: supplierId }, function(data) {
      //set values in dialog
      $('#sCompanyName').text(data.companyName);
      $('#sAddress').text(data.address);
      $('#sPostalCode').text(data.postalCode);
      $('#sCity').text(data.city);
      $('#sCountry').text(data.country);
      $('#sPhone').text(data.phone);
      $('#sHomePage').text(data.homePage);
      //get link position
      var linkPosition = $(linkElement).offset();
      //set dialog position
      $('#jqdlgSupplier').dialog('option', 'position', [linkPosition.left, linkPosition.top]);
      //open dialog
      $('#jqdlgSupplier').dialog('open');
    });
  };
</script>

And voila. We can seat and admire our grid.

There is one more thing which needs to be mentioned. If you want custom formatted column to be editable (I'm going to write about CRUD scenario soon), you need to provide unformatter function which will extract original value from cell.
As usual, example source code can be found here.