ComboBox using ExtJS and ASP.NET MVC

Introduction

Recently I've been researching a lot about the use of ExtJS JavaScript framework along with ASP.NET MVC in order to build very rich Web applications. ExtJS is a cool JavaScript library, so I want to describe another good feature of it. In this article, I want to talk about the creation of forms with combobox fields using ExtJS and ASP.NET MVC. As an illustrative example, I'm going to display a list of categories in a combobox item for the user to choose one of them. The underlying data is persisted in the Production.ProductCategory table on the AdventureWorks database shipped with SQL Server 2005/2008.

Getting started with the solution

The first step is to create a MVC application in Visual Studio.NET 2008 (see Figure 1).

ASPMVC1.gif

Figure 1

Next step is to add the ExtJS library files to the ASP.NET MVC project. Let's add the following files and directories into the Scripts directory: ext-all.js file, ext-base.js file and resources directory (see Figure 2).

ASPMVC2.gif

Figure 2

Now let's include the ExtJS library files in our solution by going to the Site.Master page and adding the references to the ExtJS files inside the head element (highlighted in yellow in the Listing 1). As well, we need to add a <asp:ContentPlaceHolder> tag element as container of the customized JavaScript and CSS code for each page (highlighted in green in the Listing 1)

<head runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />

       <!-- Include the ExtJS framework -->
    <link href="../../Scripts/ext/resources/css/ext-all.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="../../Scripts/ext/ext-base.js"></script>
    <script type="text/javascript" src="../../Scripts/ext/ext-all.js"></script>

       <!-- Placeholder to include CSS and JS files customized for each page -->
    <asp:ContentPlaceHolder ID="Scripts" runat="server" />
</head>

Listing 1

Next step is to add a controller and a default view to the ASP.NET MVC solution (see Figure 3).

ASPMVC3.gif

Figure 3

Right-click on the Index action method of the ComboBoxController class and select Add View option from the context menu (see Figure 4).

ASPMVC4.gif

Figure 4

Now let's create another JS file in the Scripts directory with necessary JS code to create a form and a combobox field inside. The code for the comboboxfieldfom.js is shown in the Listing 2. In this file, you can see that we are creating an Ext.FormPanel object containing our combobox item. This form will be rendered into the comboboxform div element. This form contains a combobox with a list of product category and a button, so when the users click on it; then the data on the form is submitted to the server (to the URL combobox/selectcategory using the GET method, so the request parameters are appended to the URL). We're using the traditional submit method by setting the standardSubmit property to true. Let's talk about the ComboBox properties. The fieldLabel property indicates the underlying label for this field. The minListWidth property sets the size of the list. The name property indicates the name of the underlying request parameter. The store property references the data source where the list of categories comes from. The displayField property is the field to be shown in the list of the combobox. The valueField property maps a key value with the shown value in displayField property. The mode property sets whether that the data is remote on a server or local. The forceSelection property forces the user to select a value from the combo, this is independent of the type of validation allowBlank. The triggerAction property indicates the action to execute when the trigger is clicked. The emptyText property is the text to be displayed when the users haven't selected anything in the combo. The editable property indicates whether you can edit on this field or not. Now we need to do a trick. If you leave the configuration in this way, and submit the form, you can see that the request parameter (category in this case) is always set to the value of displayField not the valueField as it should be. After reading in the API for Ext, I've found out that we need to set the hiddenName property to the same value of name property, in this case is category.

Finally, we have an Ext.data.JsonStore object pointing to the productcategories action method on the controller created previously in order to get the list of product category. The root property references the list of categories whose fields are Id and Name.

Ext.onReady(function() {

    var categoriesStore = new Ext.data.JsonStore({
        url: 'combobox/productcategories',
        root: 'Categories',
        fields: ['ProductCategoryID', 'Name']
    });

    var combo = new Ext.form.ComboBox({
        fieldLabel: 'Select a category',
        minListWidth : 240,
        store: categoriesStore,
        name:'category',
        hiddenName : 'category',
        displayField: 'Name',
        valueField: 'ProductCategoryID',
        typeAhead:true,
        mode:'remote',
        forceSelection: true,
        triggerAction: 'all',
        emptyText: 'Select a category...',
        editable: false
    });

    var form = new Ext.FormPanel({
        renderTo: 'comboboxform',
        width: 400,
        frame: true,
        title: 'ComboBox Example',
        bodyStyle: 'padding: 10px 10px 0 10px;',
        labelWidth: 50,
        items: combo,
        url:'combobox/selectcategory',
        method:'GET',
        standardSubmit: true,
        buttons: [{
            text: 'Click here',
            handler: function()
            {
                form.getForm().submit();   
            }
        }]
   });

});

Listing 2

Let's include the comboboxfieldfom.js (highlighted in yellow) files as well as to create the div (highlighted in green) element (where the form will be rendered) into the Index.aspx page created before (see Listing 3).

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
      Index
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Index</h2>
    <div id="comboboxform">
    </div>
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="Scripts" runat="server">
    <script type="text/javascript" src="../../Scripts/comboboxfieldfom.js"></script>
</asp:Content>

Listing 3

Now let's define the business layer's objects. We're going to define the business entity ProductCategory using Linq to SQL (see Figure 5).

ASPMVC5.gif

Figure 5

Then add the ProductCategoryRepository class and define the GetProductCategoryList method (see Listing 4).

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

namespace UploadFiles_ExtJS_MvcApp.Models
{
    public class ProductCategoryRepository
    {
        private ProductsDataContext _dcProducts = new ProductsDataContext();

        public IQueryable<ProductCategory> GetProductCategoryList()
        {
            return from p in this._dcProducts.ProductCategories
                   select p;
        }
    }
}

Listing 4

Now the final part is to define the ProductCategories action method to handle HTTP GET request from the JsonStore (pointing to the URL combobox/productcategories) to get a list of product category as well as we need the SelectCategory action method to handle HTTP GET and HTTP POST requests in order to get the selected category from the form (url is combobox/selectcategory). We also print the result in the view (see Listing 5).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using UploadFiles_ExtJS_MvcApp.Models;

namespace UploadFiles_ExtJS_MvcApp.Controllers
{
    public class ComboBoxController : Controller
    {
        //
        // GET: /ComboBox/
        public ActionResult Index()
        {
            return View();
        }

        //
        // GET: /ComboBox/
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ProductCategories()
        {
            ProductCategoryRepository repProductCategory = new ProductCategoryRepository();
            var results = (new
            {
                Categories = repProductCategory.GetProductCategoryList()
            });

            return Json(results);

        }

        [AcceptVerbs("POST", "GET")]
        public ActionResult SelectCategory(string category)
        {
            this.ViewData["CategoryID"] = category;
            return View();
        }

    }
}

Listing 5

Now let's run the solution. When you click on the combo box, you can see that the component is calling to the ProductCategories action method to get a list of product category (see Figure 6).

ASPMVC6.gif

Figure 6

When the user selects a category and click on the button, then you can see the URL generated (http://localhost:1032/combobox/selectcategory?category=1). Then the SelectCategory action method is called to get the identifier of the category and finally a view is displayed with this value (see Figure 7).

ASPMVC7.gif

Figure 7

Conclusion

In this article, I've illustrated how to create and fill combobox controls using ExtJS and ASP.NET MVC. Now you can apply this solution to your own business problems.

Resources

Here are some useful related resources:


Similar Articles