Cascading jQuery Combo Boxes in ASP.NET MVC

[Infragistics] Murtaza Abdeali / Thursday, December 1, 2011

In 2011 Volume 2, Infragistics shipped a combo box control in NetAdvantage for jQuery product. Combo box features a bunch of cool things like auto-suggest, remote filtering, multi-select etc.. One of the scenario that is quite common in today’s web applications is to have cascading combo boxes. In this post, I am going to show you how to implement exactly that using the combo box control. I am going to do this in an ASP.NET MVC application. The initial combo box will be bound to the list of items on the server and then the cascading ones will by created dynamically on the client and bound to JSON data.

To demonstrate it, I am going to use NorthWind database, and use Customer ( CustomerID, ContactName) –> Orders (OrderID,Freight) –> Order_Details (OrderID, Quantity) as my datasource and fields for my combo boxes. I am using Enitity Framework as my Model which will be connected to an embedded NorthWind instance. I will use Linq within my controller action methods to fetch and filter data.

Customer ComboBox

Since this will carry customer information that’ll come directly from the server during initial load, I will pass my data in the ViewBag and initialize my combo in the view using Razor. The code for this combo will look like as follows:

Controller:

   1: var NWE = new NORTHWNDEntities();
   2: var customer = from c in NWE.Customers
   3:              select c;
   4:  
   5: ViewBag.CustomerInfo = customer;

Razor:

   1: @(Html.Infragistics().Combo()
   2:     .ID("CustomerID")
   3:     .ValueKey("CustomerID")
   4:     .TextKey("ContactName")
   5:     .DataSource(ViewBag.CustomerInfo)
   6:     .DataBind()
   7:     .Render()
   8:  )

Order ComboBox

So far so good, the combo above was quite simple to implement. For the orders combo to show orders related to customers, we’ll need to hook an event to the customer combo such that when a user changes a customer, then we can populate it’s order information in the combo. To do that, I am going to handle the client-side event “igcomboselectionchanged” and in that event, I am first going to get the CustomerID of the selected item and use jQuery getJSON method to call my controller action. The controller action is going to filter orders by CustomerID and return it as a JSON array to the client. Upon the return of server request, I am going to grab a HTML element that is going to show the order information, and convert that into a order combo attaching it to the datasource and setting other default options.

JavaScript/jQuery:

   1: $("#CustomerID").bind("igcomboselectionchanged", function (evt, ui) {
   2:    var CustomerID = $("#CustomerID").igCombo("value");
   3:    var postData = { "CustomerID": CustomerID };
   4:  
   5:    $.getJSON("/Home/GetOrdersData", postData, function (returnData) {
   6:        $("#Orders").igCombo({
   7:            ID: "Orders",
   8:            Name: "Orders",
   9:            dataSourceType: "json",
  10:            dataSource: returnData,
  11:            textKey: "Freight",
  12:            valueKey: "OrderID",
  13:            enableClearButton: false
  14:        });
  15:    });
  16: });

The controller action method is going to take the CustomerID from the request parameter as passed in by the getJSON method call, and I’ll take that to filter orders data using Linq. Once I have the needed orders information, I can turn it into required JonResult and return it back to the client.

Controller:

   1: [HttpGet]
   2: public JsonResult GetOrdersData(string CustomerID)
   3: {
   4:     var NWE = new NORTHWNDEntities();
   5:     
   6:     var orders = from o in NWE.Orders
   7:                 where o.CustomerID == CustomerID
   8:                 select o;
   9:  
  10:     JsonResult jr = new JsonResult();
  11:     jr.Data = orders.Select(o => new { o.OrderID, o.Freight});
  12:     jr.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
  13:  
  14:     return jr;
  15: }

By doing that, now when the user selects a customer from the customer combo, the order drop down gets initialized on the client showing the order’s freight value for each of the orders.

Order_Details ComboBox

Just to take this to yet another level, I thought I’ll pull in the order details information when the user selects an order. Use the exact same approach as above, I can now use the OrderID from the order’s combobox, send it to the server, use Linq again to filter my order_details information and pass it back to the client. Generate my new order_details combo, just like how I created the order combo, attach it to data from the server and now I have it showing order_details list inside of it.

JavaScript/jQuery:

   1: $("#Orders").bind("igcomboselectionchanged", function (evt, ui) {
   2:    var OrderID = $("#Orders").igCombo("value");
   3:    var postData = { "OrderID": OrderID };
   4:  
   5:    $.getJSON("/Home/GetOrdersDetailsData", postData, function (returnData) {
   6:        $("#Order_Details").igCombo({
   7:            ID: "Orders",
   8:            Name: "Orders",
   9:            dataSourceType: "json",
  10:            dataSource: returnData,
  11:            textKey: "Quantity",
  12:            valueKey: "OrderID",
  13:            enableClearButton: false
  14:        });
  15:  
  16:    });
  17: });

Controller:

   1: [HttpGet]
   2: public JsonResult GetOrdersDetailsData(int OrderID)
   3: {
   4:     var NWE = new NORTHWNDEntities();
   5:  
   6:     var order_details = from od in NWE.Order_Details
   7:                         where od.OrderID == OrderID
   8:                         select od;
   9:  
  10:     JsonResult jr = new JsonResult();
  11:     jr.Data = order_details.Select( od => new { od.OrderID, od.Quantity} );
  12:     jr.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
  13:  
  14:     return jr;
  15: }

Summary

Cascading combo boxes is a widely used scenario in web applications today. It is a neat and easy to  add to the performance and scalability of the entire application without getting in the way of user experience. With the combo box control that shipped in 2011 Volume 2 of NetAdvantage for jQuery, implementing this scenarios is as easy as it can get. Just using the simple client events to grab combo values and using jQuery to call controller actions that can filter and send back the right data makes it fairly easy to implement.

Hope you enjoyed this blog post.