Forms with ExtJS and ASP.NET MVC

Introduction

After researching a lot about ExtJS support for rich Internet applications and nice user experience, and for my bias to this JavaScript library, I’ve decided to write this article to illustrate the form support in ExtJS and how it’s well integrated with ASP.NET MVC framework. First of all, I will explain the form support in ExtJS and then we will walk through an illustrative example where we put in practice what we’ve learnt before with a real-world solution by creating, validating and submitting information to the server.

Explaining the forms support in ExtJS

In order to create forms in ExtJS, we have to instantiate objects of the class Ext.FormPanel. This class implements all the functionality of common HTML forms and corresponds to the <form> HTML tag. Let’s create our first empty form in ExtJS (see Listing 1). The title property, bodyStyle, width and html properties are self-descriptive. The renderTo points to a <div> element where the form will be rendered. The defaults property specifies the default component on the form. The url property specifies the URI send the request of the form. And finally, the html property specifies a text as the default output (see Listing 1).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

html: ‘This form is empty!’

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 1

The output is shown in the Figure 1.

Figure 1

Next step is to add different fields to this form. In order to add fields, we need to set the items property instead of working on the html property. The first two elements to add are a text field and a number field (see Listing 2).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

 

var nameTextField = new Ext.form.TextField({

fieldLabel: ‘Name’,

name: ‘name’

});

var ageNumberField = new Ext.form.NumberField({

fieldLabel: ‘Age’,

name: ‘age’

});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

nameTextField, ageNumberField

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 2

In ExtJS fields, we can find several components and its properties. In this case, the most important properties are: fieldName property to set a descriptive message accompanying the component of the form and name property to set name of the request parameter. The emptyText property defines the text that the field will contain when it is empty. The value property is the default value for the control. The output is shown in Figure 2.

Figure 2

Another way to declare controls is on the fly (highlighted in yellow in the Listing 3). As you can see for the name field we don’t have to specify the type because it’s taken from the defaults property of the form, unlike the type of the age field which is specified by the xtype property.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 3

Let’s add new elements to the form. For radio buttons, the code is shown in Listing 4 highlighted in yellow. The important thing here is to set the name to the same value.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 4

And the output is shown in the Figure 3.

Figure 3

Next element is checkbox. The checkboxes are used to select one or more items from a list, or simply to activate or deactivate any flag or permission in a system. The code is shown in the Listing 5 highlighted in yellow.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 5

The radio buttons are used to select a single choice of several items. The result is shown in the Figure 4.

Figure 4

The hidden fields are useful to send information to the server that the user doesn’t need to know, such as id of the record being edited, or a security token, and so on. ExtJS has the component “Ext.form.Hidden” which allows us to achieve this functionality. See in the Listing 6 highlighted in yellow.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 6

The combobox field is a list of pairs (key and value). The key identifies the pair and is usually submitted to the server, while the value is what users can see in the browser when he selected one from the available options.
In order to initialize the values of a combobox field, we need to use store objects, where data can be kept.

The code for the combobox is shown in the Listing 7 highlighted in yellow.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 7

And the output is shown in the Figure 5.

Figure 5

To select a particular date, we need to use the datefield            element (see Listing 8 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 8

The output is shown in the Figure 6.

Figure 6

If you only want to select the time (not the date), you need to use timefield (see Listing 9 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 9

And the output is shown in the Figure 7.

Figure 7

We also have a text area representation in ExtJS (see Listing 10 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

this.form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’remoteurl’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’},

{xtype: ‘textarea’,name: ‘area’,fieldLabel: ‘Memo’,anchor: ‘90%’,multiline: true}

]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 10

The output is shown in the Figure 8.

Figure 8

So far, we have developed a form using ExtJS to take data from the user. Now, I will show how to send the data to the server. To send the data, we need to add a button to the form to handle the submit process (see Listing 11 highlighted in yellow). The buttons property is list of button for the form. Each button has name and handler properties. The handler property contains the logic associated to the action executed on the button. In this case, we have two buttons whose names are Save and Reset. The Save button’s handler executes a submit action on the form and shows a message indicating success or failure. The Reset button’s handler resets the field values on the form.

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

var form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’submitform’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’},

{xtype: ‘textarea’,name: ‘area’,fieldLabel: ‘Memo’,anchor: ‘90%’,multiline: true}

],

buttons: [{

text: ‘Save’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, b.result.error);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 11

And the last step in the form creation is the validation. Validation is a very important topic and useful because every data entry contains invalid data. In this part of the article, we’re going to talk about the underlying techniques in ExtJS.

In order to specify required fields, we need to set the allowBlank property to false. Let’s see the techniques for name and age properties (see Listing 12 highlighted in yellow).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

var answers = new Ext.data.SimpleStore({

fields: [‘id’, ‘answer’],

data: [[‘1’, ‘yes’], [‘2’, ‘no’]]});

var form= new Ext.FormPanel({

title:’Test form’,

renderTo: ‘frame’,

width: 400,

url:’home/saveform’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Name’,name:’name’, allowBlank:false},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’, allowBlank:false},

{xtype: ‘radio’,fieldLabel: ‘Sex’,name: ‘sex’,boxLabel: ‘male’},

{xtype: ‘radio’,name: ‘sex’,hideLabel: false, boxLabel: ‘female’},

{xtype: ‘checkbox’,name: ‘siblings’,fieldLabel: ‘Siblings’},

{xtype: ‘hidden’,name: ‘developer’,value: ‘john olamendy’},

{xtype: ‘combo’,store: answers,mode: ‘local’,fieldLabel: ‘Answers’,name: ‘answer’,displayField: ‘answer’,valueField: ‘id’},

{xtype: ‘datefield’,name: ‘date’,fieldLabel: ‘Select a date’,anchor: ‘90%’},

{xtype: ‘timefield’,name: ‘time’,fieldLabel: ‘Time’,anchor: ‘90%’},

{xtype: ‘textarea’,name: ‘area’,fieldLabel: ‘Memo’,anchor: ‘90%’,multiline: true}

],

buttons: [{

text: ‘Save’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

 

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 12

When you run the application and click on the Save button without entering any data on the Name and Age field, then you receive an error message and the required fields are underlined in red.

To customize the error messages on the fields, we need to add the following line of code just under the Ext.onReady function (see Listing 13).

Ext.QuickTips.init();

Listing 13

Now, when the users move the mouse over the field, they will see a balloon with a message displaying the error (see Figure 9).

Figure 9

For number fields like the Age field, we have a lot of properties to validate the data such as maxValue, allowNegative, allowDecimals, allowBlank and minValue.

ExtJS has a good support for validation using regular expressions. You can learn more about this feature.

Getting started with the solution

Now, we’re going to create an example solution using ExtJS library and ASP.NET MVC. We’re going to implement the Add Employee use case for a Human Resources Management system. The Add Employee use case description is as follows: A screen prompts the user to enter valid information (whether optional or mandatory) for a new employee such as employee identifier, full name, address, age, salary and department. The department field is a list of department to choose one.

This use case fits well to illustrate the main artifacts and steps for a solution using ExtJS and ASP.NET. The implementation strategy for this use case is to create an ExtJS form on the client-side and process the data using ASP.NET MVC. The persistence layer will be Linq to represent business entities and to persist data to the database system. As the development environment we’re going to use Microsoft Visual Studio.NET and as the database system Microsoft SQL Server.

Open Visual Studio.NET and create a ASP.NET MVC application.

The first step is to create the database schema for the use case. Our schema will contain two entities: employee and department. Let’s create the HumanResources database and the underlying tables and its constraints in order to maintain the data integrity (see Listing 14).

 

create table department

(

deptno varchar(20) primary key,

deptname varchar(50) not null,

location varchar(50)

);

create unique index undx_department_deptname on department(deptname);

 

insert into department

values(‘HQ-200′,’Headquarter-NY’,’New York’);

insert into department

values(‘HR-200′,’Human Resources-NY’,’New York’);

insert into department

values(‘OP-200′,’Operations-NY’,’New York’);

insert into department

values(‘SL-200′,’Sales-NY’,’New York’);

insert into department

values(‘HR-300′,’Human Resources-MD’,’Maryland’);

insert into department

values(‘OP-300′,’Operations-MD’,’Maryland’);

insert into department

values(‘SL-300′,’Sales-MD’,’Maryland’);

 

create table employee

(

empno varchar(20) primary key,

fullname varchar(50) not null,

address varchar(120),

age int,

salary numeric(8,2) not null,

deptno varchar(20) not null,

constraint fk_employee_department_belong_rltn foreign key(deptno)

references department(deptno)

);

create unique index undx_employee_fullname on employee(fullname);

Listing 14

Then let’s create a Linq to SQL Classes item inside the Model folder to define the structure of the entities and the persistence mechanism (see Listing 13). The object definition in Linq to SQL is shown in the Figure 10.

Figure 10

Next step is to develop the EmployeeRepository class to manage the data access logic to the employee table (CRUD operations). Regarding to our use case, we only need to implement the create operation (see Listing 15).

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 HumanResources_ExtJSASPNETMVC.Models

{

public class EmployeeRepository

{

private HumanResourcesDataContext _ctxHumanResources = new HumanResourcesDataContext();

 

public void Create(employee employee)

{

this._ctxHumanResources.employees.InsertOnSubmit(employee);

this._ctxHumanResources.SubmitChanges();

}

}

}

Listing 15

We also need to develop the DepartmentRepository class to manage the data access logic to the department table (CRUD operations). Regarding to our use case, we only need to implement the read operation in order to find a list of department (see Listing 16).

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 HumanResources_ExtJSASPNETMVC.Models

{

public class DepartmentRepository

{

private HumanResourcesDataContext _ctxHumanResources = new HumanResourcesDataContext();

 

public IQueryable<department> FindAll()

{

return from dept in this._ctxHumanResources.departments

orderby dept.deptname

select dept;

}

}

}

Listing 16

Now that we have defined the business logic’s artifacts, that is the business entities and the services that process the entities, we need to go to the presentation layer. The implementation strategy for the presentation layer is ASP.NET MVC. MVC stands for model-view-controller. We have worked on the model piece of the architecture before. Now let’s define another important piece of the architecture: the controller.

Right-click on the Controllers folder in the Solution Explorer window and select Add|Controller option from the context menu. Set HumanResourcesController as the name (see Figure 11).

Figure 11

Now let’s go to the presentation piece to define the graphical interface using ExtJS JavaScript library. The first step is to download and copy the distribution of ExtJS inside the Scripts directory. For our solution, we only need ext-all.js file, ext-base.js file and the resources directory (see Figure 12).

Figure 12

Now let’s include this library in our project. For this purpose, let’s go to the Site.Master page and adding the references to the ExtJS files inside the head element (highlighted in yellow in the Figure 13). 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 Figure 14).

<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>

Figure 13

Now let’s add the view to present the form to get the data related to one employee. Go to the HumanResourcesController controller and right-click on the Index action method and select Add View option from the context menu. Click on the Add button on Add View dialog box (see Figure 14).

Figure 14

In order to implement the ExtJS form, we need to add a JavaScript file to the Scripts directory (see Figure 15).

Figure 15

Then include the JavaScript file and add a div element (with id=employeeform) into the Index.aspx view (see Listing 17).

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

 

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

Add a New Employee

</asp:Content>

 

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

 

<h2>Add a New Employee</h2>

<div id=”employeeform”></div>

</asp:Content>

 

<asp:Content ID=”Content3″ ContentPlaceHolderID=”Scripts” runat=”server”>

<script type=”text/javascript” src=”../../Scripts/employee_form.js”></script>

</asp:Content>

Listing 17

Now it’s time to go to the employee_form.js file and write some code in JavaScript to configure the ExtJS form and its underlying widgets.

The first step is to define an instance of Ext.data.JsonStore class to get a list of department. The url property points to the departments action method on the HumanResourceController controller. This method is access by default http access method which is POST. The root property is the root element of the list of departments. The fields property specifies the data fields (see Listing 18).

    var departmentStore = new Ext.data.JsonStore({

url: ‘humanresource/departments’,

root: ‘departments’,

fields: [‘deptno’, ‘deptname’]

});

Listing 18

Next step is to define the form. The properties are self-descriptive. In this case, the url property points to the AddEmployee action method on the HumanResourceController controller. This method is also accessed using POST HTTP verb (see Listing 19).

var form= new Ext.FormPanel({

title:’Add Employee Form’,

renderTo: ’employeeform’,

width: 400,

url:’humanresource/addemployee’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

Listing 19

The items property is the list of widgets for the fields of the form. Here the default widget is textfield (this is specified in the defaults property). The first field is employee number which is required (specified by the allowBlank property) textfield. The second field is the fullname which is also a required textfield. The address field is an option textarea. The age field is an optional numberfield. The salary field is a required numberfield. And finally, the department number field is identifier string which is selected from a list of departments (see Listing 20).

          items:[

{fieldLabel:’Employee ID’,name:’empno’, allowBlank:false},

{fieldLabel: ‘Fullname’,name: ‘fullname’, allowBlank:false},

{xtype: ‘textarea’,fieldLabel: ‘Address’,name: ‘address’,multiline: true},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype:’numberfield’,fieldLabel:’Salary’,name:’salary’, allowBlank:false},

{xtype:’combo’,fieldLabel:’Department’,name:’deptno’, store:departmentStore,

hiddenName:’deptno’,displayField:’deptname’,valueField:’deptno’,typeAhead:true,

mode:’remote’,forceSelection: true,triggerAction: ‘all’,emptyText: ‘Please, select a department…’,

editable: false}

],

Listing 20

Then the buttons property is defined (see Listing 21).

        buttons: [{

text: ‘Add’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

Listing 21

After add the line of code of the Listing 13, you have the complete employee_form.js file (see Listing 22).

Ext.ns(‘formextjs.tutorial’);

 

Ext.BLANK_IMAGE_URL = ‘../ext/resources/images/default/s.gif’;

 

formextjs.tutorial.FormTutorial = {

init: function(){

//Begin of code   here

Ext.QuickTips.init();

var departmentStore = new Ext.data.JsonStore({

url: ‘humanresource/departments’,

root: ‘departments’,

fields: [‘deptno’, ‘deptname’]

});

var form= new Ext.FormPanel({

title:’Add Employee Form’,

renderTo: ’employeeform’,

width: 400,

url:’humanresource/addemployee’,

defaults:{xtype:’textfield’},

bodyStyle:’padding: 10px’,

items:[

{fieldLabel:’Employee ID’,name:’empno’, allowBlank:false},

{fieldLabel: ‘Fullname’,name: ‘fullname’, allowBlank:false},

{xtype: ‘textarea’,fieldLabel: ‘Address’,name: ‘address’,multiline: true},

{xtype:’numberfield’,fieldLabel:’Age’,name:’age’},

{xtype:’numberfield’,fieldLabel:’Salary’,name:’salary’, allowBlank:false},

{xtype:’combo’,fieldLabel:’Department’,name:’deptno’, store:departmentStore,

hiddenName:’deptno’,displayField:’deptname’,valueField:’deptno’,typeAhead:true,

mode:’remote’,forceSelection: true,triggerAction: ‘all’,emptyText: ‘Please, select a department…’,

editable: false}

],

buttons: [{

text: ‘Add’,

handler: function()

{

form.getForm().submit({

success: function(a, b)

{

Ext.Msg.alert(‘Success’, ‘ok’);

},

failure: function(a, b)

{

Ext.Msg.alert(‘Failure’, ”);

}

});

}

},

{

text: ‘Reset’,

handler: function()

{

form.getForm().reset();

}

}]

});

//End of code here

}

}

 

Ext.onReady(formextjs.tutorial.FormTutorial.init,formextjs.tutorial.FormTutorial);

Listing 22

Now let’s go to the HumanResourceController and implement the corresponding action methods (see Listing 23).

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Ajax;

using HumanResources_ExtJSASPNETMVC.Models;

 

namespace HumanResources_ExtJSASPNETMVC.Controllers

{

public class HumanResourceController : Controller

{

DepartmentRepository _repoDepartment = new DepartmentRepository();

EmployeeRepository _repoEmployee = new EmployeeRepository();

 

//

// GET: /HumanResource/

public ActionResult Index()

{

return View();

}

 

//

// POST: /HumanResource/Departments

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Departments()

{

var arrDepartment = this._repoDepartment.FindAll();

var results = (new

{

departments = arrDepartment

});

return Json(results);

}

 

//

// POST: /HumanResource/AddEmployee

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult AddEmployee(employee employee)

{

string strResponse = String.Empty;

try

{

this._repoEmployee.Create(employee);

strResponse = “{success: true}”;

}

catch (Exception)

{

strResponse = “{success: false, error: \”An error occurred\”}”;

}

return Content(strResponse);

}

 

}

}

Listing 23

Now let’s run the solution (see Figure 16).

Figure 16

And when you click on the Add button, you see the result (see Figure 17).

Figure 17

And the row inserted in the dbo.employee table on the database (see Figure 18).

Figure 18

Conclusion

In this article, I’ve explained the form support of ExtJS and then we’ve walked through an illustrative example where we’ve put in practice all these concepts with a real-world solution by creating, validating and submitting information to the server.

5 thoughts on “Forms with ExtJS and ASP.NET MVC

  1. Pingback: MVP Factor

  2. Pingback: Fernando Garcia Lorea

  3. Hi John,
    Very Good Post,Exactly meets my requirements. I have tried it and its working for saving the employee data. I have made some changes in the employee table, allowed null for department. because I am not getting the department data in combo box.could you help me out in this.Apart from it every thing is working fine.
    could you post a sample application about how to bind the data to the form using extjs4 with Asp.net MVC3.

    Thanks in advance…

  4. Hello John very nice post. Is there any other sample application like this to send a mail from asp.net mvc application using Extjs 4 as a email screen.If so could you post it As soon as possible.
    thanks in advance

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s