Download Source Code (5.69 mb)

Introduction

jQuery simplyfies everything with mobile development that can run on different platform - iphone, android, and ipad to name a few. With jQuery Theme Roller you can design your mobile UI in a fly and with its custom attributes like data-role, data-filter, and data-inset it can add some more flavor on your application. Like for instance when data-filter is set to true, a list search will automatically available for you without extra coding.

jQuery mobile comes with a core CSS library that manages UI rendering and styling that is optimized for mobile devices.

In Visual Studio 2010 and MVC 4, it has a built in MVC for mobile project that you can use to automatically create a mobile solution with default theme and jquery mobile already included. It also have jquery packages ready for you to use. I'm using Visual Studio 2010, MVC 4 Beta 1, and Razor syntax throughout this article.

With the simple html code below it will generate a user interface you see in image 1.0. And by just adding data-filter="true" it automatically enables filtering for you in a fly without extra code, neat!!! see image 2.0. One nice feature with it is that all your graphics, styles, and animations (like page transitions) are already handled by framework. You can also create theme in a fly using jQuery Theme Roller.

NOTE: jQuery is cross platform and programming language independent you can use other programming language to develop like PHP and Ruby.

<ul data-role="listview" data-filter="true">
    <li data-role="list-divider">A</li>
    <li><a href="#">Abello, Jennifer</a></li>
    <li><a href="#">Aguilar, Noel</a></li>
    <li data-role="list-divider">C</li>
    <li><a href="#">Cerrada, Rodolfo</a></li>
    <li><a href="#">Cerrada, Maribel</a></li>
    <li><a href="#">Cordial, Randell</a></li>
    <li data-role="list-divider">O</li>
    <li><a href="#">Orozco, Richard</a></li>
    <li><a href="#">Ong, Abegail</a></li>
    <li data-role="list-divider">P</li>
    <li><a href="#">Prino, Jho</a></li>
    <li><a href="#">Prino, Migo</a></li>
</ul>

 

Image 1.0. jQuery mobile list

Image 2.0. Filtered list based on the character entered in the search box.

Basics

Opps! Don't get too excited those are just teasers, lets start with the basics. JQuery basic structure is to devide the body into 1 parent container the page and 3 basic section the header, content, and footer using the data-role attribute of DIV tags (see html below). Once this basic structure is defined, jQuery will manage the rendering of the page and its controls you see in image 1.0 and 2.0.

 

<!DOCTYPE html>
<html lang="en">
    <head>
    </head>
    <body>

        <div data-role="page" data-theme="b">
            <div data-role="header">
                <!-- header goes here -->
            </div>

            <div data-role="content">
                <!-- body content goes here -->
            </div>

            <div data-role="footer">
                <!-- footer goes here -->
            </div>

        </div>
    </body>
    
</html>

The page is parent container that holds the header, content, and footer sections.

The header section, contains the title, global navigation or menu, and company logo. This is always a child of the page parent container.

The content section, contains the contents of the page. This section of the page always dynamic or varies depending on the page you are viewing. This is always child of the page parent container and same level as the header and footer.

The footer section, contains the footer information like copyright and site information. this is always child of the page parent container and same level as the header and content.

Lets Get It On!

Now we are done with the basics, we will create a sample application that demonstrate the jQuery mobile. Before we start please do the following:

If you are not a .NET developer, just follow the walkthrough and just focus on html tags and elements. I juse ASP.NET MVC layouts and themes but undernethe, its just HTML5 and jQuery.

Now fire up your Visual Studio and follow the steps below to create a ASP.NET MVC mobile project.

  1. Create New Project. Select Web and ASP.NET MVC 4 Web Application project and click OK.

  2. On the New ASP.NET MVC 4 Project window, select the Mobile Application and click OK.

    MVC Mobile Application

  3. After successfully creating project, press F5 to run the application. This will show you the mobile application in action. I suggest to view it in Chrome or Safari browser to feel the slide transition when you click a button. IE and Firefox does not support it at this time.

    MVC Project

  4. Now we have the basic project structure lets modify it to include our test pages. Stop the running application and add Employee controller under Controllers folder. Right click the Controllers folder and select Add -> Controller... from the context menu. Enter EmployeeController and select Controller with empty read/write actions.

  5. Add EmployeeModel class under Models folder. This will serve as our model structure for the page.
  6. Create a view for our list by right clicking the Index action in our controller and select Add View... from the context menu. It will launch the Add View form.

    Add View

  7. In the Add View form, leave the name as Index, select Razor as View Engine, and select _Layout.cshtml as our layout. If the layout or master page is empty click the browse button besides it and select the desired layout. Then click Add button. This will create Index.cshtml under Views\Employee folder. By the way, Layout is equivallent to master page in ASPX view engine.

  8. Open Index.cshtml and Modify ViewBag.Title to "Employee List".
    @{
        ViewBag.Title = "Employee List";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
  9. Define the model that the page will consume.
    @model  IEnumerable<MobileMvc.Models.EmployeeModel>
  10. Define the header section. Data and markup in this section will replace the @RenderSection("Header") of _Layout.cshtml. In our case we will define a header that has back button, page title, and add button. This is equivallent to ContentPlaceHolder of ASPX view engine.
    @section Header
    {
        <a href="/Home/" data-icon="back" data-rel="back">Back</a>
        <h2>@ViewBag.Title</h2>
        <a href="/Employee/Create" data-icon="plus">Add</a>
    }
  11. Add the content of the page. This will be replace the @RenderBody() of the _Layout.cshtml.
    <ul data-role="listview" data-theme="c">
        @{
            string name = String.Empty;
                
            foreach (MobileMvc.Models.EmployeeModel item in this.Model)
            {
                name = item.GetFullname(); 
    
                <li>@Html.ActionLink(name, "Details/" + item.EmployeeID.ToString(), "Employee")</li>
            }
        }
    </ul>
  12. Next, we need to populate the page with the employee data. Do do this we need to go back to EmployeeController and create a method that will return list of Employees.
    #region --- SAMPLE DATA: Temporary substitute for Data access lateyer ----
    
            private IList<EmployeeModel> GetEmployees()
            { 
                List<EmployeeModel> list = new List<EmployeeModel>();
    
                EmployeeModel item = new EmployeeModel()
                {
                    EmployeeID = 1,
                    BirthDate = new DateTime(1978, 4, 12),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 3,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Rod",
                    Lastname = "Cerrada",
                    MaritalStatus = 2 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 2,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 3,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Maribel",
                    Lastname = "Cerrada",
                    MaritalStatus = 2 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 3,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 0,
                    EmployeeType = 3,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Randell",
                    Lastname = "Cordial",
                    MaritalStatus = 1 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 4,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 0,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Jennifer",
                    Lastname = "Abello",
                    MaritalStatus = 2 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 5,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 3,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Prino",
                    Lastname = "Jhocelyn",
                    MaritalStatus = 2 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 6,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 2,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Orozco",
                    Lastname = "Richard",
                    MaritalStatus = 2 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 7,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 0,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Prino",
                    Lastname = "Jobel",
                    MaritalStatus = 1 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                item = new EmployeeModel()
                {
                    EmployeeID = 8,
                    BirthDate = new DateTime(1979, 10, 6),
                    Company = "Cerquit Solutions, Inc.",
                    Dependents = 3,
                    EmployeeType = 1,   //-- 1 = regular, 2 = contractual, 3 = probational
                    Firstname = "Jose",
                    Lastname = "Garcia",
                    MaritalStatus = 2 //-- 1- single; 2= married; 3= separated
                };
    
                list.Add(item);
    
                list.Sort();
    
                return list;
            }
    
            #endregion
  13. After creating the GetEmployees() method, modify the Index() action to load the data. Remember that we define the model as IEnumerable<EmployeeModel> in Step #9 so we need to return list of employees. The method we created above only returns dummy list of employee data.
    public ActionResult Index()
    {
        IList<EmployeeModel> list = GetEmployees();
    
        return View(list);
    }
  14. Next, we need to make the list visible to home page that way our user can navigate to Employee List. To do this go to View\Home\Index.cschtml and append Employee List link after the Contact link.
    <ul data-role="listview" data-inset="true">
        <li data-role="list-divider">Navigation</li>
        <li>@Html.ActionLink("About", "About", "Home")</li>
        <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
        <li>@Html.ActionLink("Employee List", "Index", "Employee")</li> <!-- Employee List Link -->
    </ul>
  15. Now run the application by pressing F5. In the home page, click the employee list. This will redirect you to the Employee list page.

Next we will create the Details page for the user to view the details of the selected employee.

Building Details Page

Now, we have the list we need a page for the user to view the details of the employee.

  1. Go to EmployeeController.cs, and right click the Details() action and select Add View... from the context menu to create a Details view. Use the same settings when we create Index view above.
  2. Modify the ViewBag.Title to display the name of the employee, define EmployeeModel as model the page model, and create header section with Back and Edit button. Back button will redirect the user back to previous page and Edit button will redirect the user to Edit page.
    @{
        ViewBag.Title = @Model == null? "Not Found" : @Model.GetFullname() + " - Details";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    @model MobileMvc.Models.EmployeeModel
    
    @section Header
    {
        <a href="/Home/" data-icon="back" data-rel="back">Back</a>
        <h3>@ViewBag.Title</h3>
        <a href="/Employee/Edit/@this.Model.EmployeeID" data-icon="check">Edit</a>
    }
  3. Create a footer section that will contain the delete button to allow user to delete the record. Note the data-prefetch attribute, it will preload the DeleteDialog.htm in the page that way it will be ready by the time the page needs it.
    @section Footer
    {
        <a href="/DeleteDialog.htm" onclick="InitializeDeleteDialog();"
             data-role="button" data-icon="delete" data-inline="true" 
             data-rel="dialog" data-prefetch>Delete</a>
    }
  4. Create the content of the page that will display the details of the employee. We just mark the textboxes as readonly for viewing only.
    <input type="hidden" id="EmployeeID" name="EmployeeID" value="@Model.EmployeeID" />
    <input type="hidden" id="dialogItemText" value="@Model.GetFullname()" />
    <div data-role="fieldcontain">
    		<label for="isActive"> </label>
    		<select name="isActive" id="isActive" data-role="slider" disabled>
    			<option value="0" >Not Active</option>
    			<option value="1" >Active</option>
    		</select> 
    </div>
    <div data-role="fieldcontain">
    	<fieldset data-role="controlgroup" data-type="horizontal" disabled >
    		    <legend>Marital Status</legend>
    			<input type="radio" name="radioMaritalStatus" id="radioMaritalStatusSingle" value="1" @if(@Model.MaritalStatus == 1){@Html.Raw("checked=\"checked\"");} />
    			<label for="radioMaritalStatusSingle">Single</label>
    			<input type="radio" name="radioMaritalStatus" id="radioMaritalStatusMarried" value="2" @if(@Model.MaritalStatus == 2){@Html.Raw("checked=\"checked\"");} />
    			<label for="radioMaritalStatusMarried">Married</label>
                <input type="radio" name="radioMaritalStatus" id="radioMaritalStatusSeparated" value="3" @if(@Model.MaritalStatus == 3){@Html.Raw("checked=\"checked\"");} />
    			<label for="radioMaritalStatusSeparated">Separated</label>
    	</fieldset>
    </div>
    <div data-role="fieldcontain">
        <label for="Lastname">Lastname</label>
        <input type="text" name="Lastname" id="Lastname" value="@Model.Lastname" readonly />
    </div>
    <div data-role="fieldcontain">
        <label for="Firstname">Firstname</label>
        <input type="text" name="Firstname" id="Firstname" value="@Model.Firstname" readonly />
    </div>
    <div data-role="fieldcontain">
        <label for="Company">Company</label>
        <input type="text" name="Company" id="Company" value="@Model.Company" readonly />
    </div>
    <div data-role="fieldcontain">
        <label for="BirthDate">Birthdate</label>
        <input type="date" name="BirthDate" id="BirthDate" value="@Model.BirthDate" readonly />
    </div>
    <div data-role="fieldcontain">
        <label for="Dependents">Dependents</label>
        <input type="range" name="Dependents" id="Dependents" value="@Model.Dependents" min="0" max="30" readonly disabled />
    </div>
    <div data-role="fieldcontain">
    	<fieldset data-role="controlgroup" data-type="vertical" disabled>
    		    <legend>Employment Type</legend>
    			<input type="radio" name="radioEmploymentType" id="radioEmploymentTypeRegular" value="1" @if(@Model.EmployeeType == 1){@Html.Raw("checked=\"checked\"");} />
    			<label for="radioEmploymentTypeRegular">Regular</label>
    			<input type="radio" name="radioEmploymentType" id="radioEmploymentTypeContractual" value="2" @if(@Model.EmployeeType == 2){@Html.Raw("checked=\"checked\"");} />
    			<label for="radioEmploymentTypeContractual">Contractual</label>
                <input type="radio" name="radioEmploymentType" id="radioEmploymentTypeProbational" value="3" @if(@Model.EmployeeType == 3){@Html.Raw("checked=\"checked\"");} />
    			<label for="radioEmploymentTypeProbational">Probational</label>
    	</fieldset>
    </div>
  5. Modify Index.cshtml to point to detalis page.
    <li>@Html.ActionLink(name, "Details/" + item.EmployeeID.ToString(), "Employee")</li>
  6. Now we need to create dialog for delete to confirm the action. Create DeleteDialog.htm and add the script below. Save it. In my case I save it in the root. This is the page we reference in delete button in step #3.
    <div data-role="page" id="deleteDialogPageEdit" data-overlay-theme="b">
            <div data-role="header" data-theme="b">
                <h2>Delete</h2>
            </div>
    
            <div data-role="content" data-theme="d">
                <p>
                Are you sure you want to delete <span id="itemName">selected item</span>?
                </p>
    
                <div style="text-align:right">
                    <a data-role="button" href="#" data-rel="back" data-theme="b" data-inline="true">No </a>
                    <a data-role="button" href="#" data-theme="d" data-inline="true" data-icon="check" id="deleteButton" >Yes</a>
                </div>
            </div>
        </div>
  7. Then we added a javascript method in _Layout.cshtml to initialize the Yes button link. that way when the user click Yes button it will trigger the delete. If you have specific dialog for each delete where you hardcode the link or script to do the delete, you don't need this.
    //-- initialized delete dialog url
    function InitializeDeleteDialog() {
        $("#itemName").text($("#dialogItemText").val());
        //NOTE: This is not a good way to delete, use ajax Post to trigger delete. This is for the sake of demo.
        $("#deleteButton").attr("href", "/Employee/Delete/" + $("#EmployeeID").val());
    }
  8. Press F5 to run the application. Go to Employee List, then select the employee to view. It will show you this page.

  9. To create the Edit page, just repeat step 1 to 8 and just remove the readonly attribute in each control or you can download the source code. Be sure to link Detail page's Edit button to Edit page.

In this article I walk you through the jquery moble and how it helps developers to create powerful mobile applications that can be viewed in different mobile devices like iPhone, iPad, android, blackberry, and a lot more. In most cases you need to have a separate View for each platform you want to target that way you could customize the user interface specific device's screen size, resolution, and supported elements.

You can download the complete source code here.

May the force be with you!

References