Tuesday, April 22, 2014

MVC 4 WebGrid – Filtering on Selected Columns with DropDownLists in Header

This example demonstrates a MVC 4 WebGrid implementation to display subsets of data filtered using drop-down lists embedded in grid column headers. Example grid has two columns 'Code' and 'Status'.  A filter dropdown list is added in the 'Status' column header, which contains all the unique values within the column. This filter dropdown list is populated using ViewBag and filtering is happening on its item change postback. A postback is forced on onchange event of the drop-down list using jQuery.

WebGrid control header doesn't support inserting HTML directly. Therefore this implementation uses MvcHtmlString class and simple string replace to insert a dropdown control to the header. I use a placeholder called '{StatusFilter}' in the header initially and then replace that with the HTML markup for the dropdown list.

View:

@model hub.Models.MyCampModel

@{
  if (Model != null && Model.MyCampaigns != null 
          && Model.MyCampaigns.Count() > 0)
  {
   using (Html.BeginForm())
   {       
    var grid = new WebGrid();
    grid.Bind(Model.MyCampaigns, rowCount: Model.MyCampaigns.Count());
    grid.Pager(WebGridPagerModes.All);
   
    @MvcHtmlString.Create(grid.GetHtml(
     tableStyle: "main_table_wrapper",
      alternatingRowStyle: "descending",
     rowStyle: "ascending",
     columns: grid.Columns(
      grid.Column("StatusCode", header: "Code"),
      grid.Column("Status", header: "Status {StatusFilter}"))  
    ).ToString().Replace("{StatusFilter}", Html.DropDownList("RequestStatusFilter", ViewBag.ReqStatusOptions as SelectList, "All", new { onchange = "$(this).closest('form').submit();" }).ToString()));
   }   
  } 
}


Post action to get filtered results:

[HttpPost]
public ActionResult CampaignList(string requestStatusFilter = "")
{
  MyCampModel model = new MyCampModel();
  model.MyCampaigns = new List<MyCampaign>();
  var myRecs = db.MyCampaigns.Where(itm => (string.IsNullOrEmpty(requestStatusFilter) || itm.MyCampaignStatus.Name == requestStatusFilter));
  foreach (var rec in myRecs)
  {
    MyCampaign myCamp = new MyCampaign() { StatusCode = rec.Code, Status = rec.MyCampaignStatus.Name };
    model.MyCampaigns.Add(myCamp);
  }
  return View(model);
  ViewBag.ReqStatusOptions = new SelectList( // logic to select statuses.
}

Here the drop-down list is rendered in addition to the header text. Therefore sorting by column headers is also available in the same time.

1 comment:

Vikram said...

Good post for more complete details on Web grid visit Implementing WebGrid in MVC (Step by step integration)
Thanks