Using an ASP.NET DataRepeater ItemTemplate to create a jQuery Mobile Nested List with List Dividers

The jQuery Mobile framework has a list view widget that displays unordered lists in several different ways.  In the process of converting the Microsoft Global MVP Summit mobile site to use jQuery Mobile I wanted to change the way I displayed the events.  The idea was to have a header for each date that there was an event along with some of the details of the event.  Clicking on the event would take you the to event details page.

To accomplish this I used the count bubble, list dividers, content formatting and the search filter bar features of jQuery Mobile.

First let’s look at the HTML, for the sake of brevity I removed the ID fields from the HTML.

  1: <ul data-role="listview" data-inset="true" data-theme="d" data-filter="true">
  2:     <li data-role="list-divider">2/25/2012<span id="EventCount_0" class="ui-li-count">1</span></li>
  3:     <li>
  4:     <a href="/m/e.aspx?Id=45">
  5:         <h3><span>Northwest Harvest at MVP Summit 2012</span></h3>
  6:         <p><strong><span>Northwest Harvest Warehouse</span></strong></p>
  7:         <p class="ui-li-aside"><span>from 11:30 AM to 5:00 PM</span></p>
  8:     </a>
  9:     </li>
 10:     <li data-role="list-divider">2/27/2012<span class="ui-li-count">2</span></li>
 11:     <li>
 12:     <a href="/m/e.aspx?Id=48">
 13:         <h3><span>Consumer Camp: Bellevue</span></h3>
 14:         <p><strong><span id="VenueName_0">Microsoft Store: Bellevue</span></strong></p>
 15:         <p class="ui-li-aside"><span>from 5:00 PM to 8:00 PM</span></p>
 16:     </a>
 17:     </li>
 18:     <li>
 19:     <a href="/m/e.aspx?Id=46">
 20:         <h3><span>First Time MVPs Event</span></h3>
 21:         <p><strong><span>Rockbottom - Top of the Rock</span></strong></p>
 22:         <p class="ui-li-aside"><spa>from 6:00 PM to 9:00 PM</span></p>
 23:     </a>
 24:     </li>
 25: </ul>

From this HTML markup the jQuery Mobile framework will generate a view that looks like this:

image

The jQuery Mobile ListView

Creating the ListView

The start of the unordered list, Line 1, has 4 attributes:

  1: <ul data-role="listview" 
  2: data-inset="true" 
  3: data-theme="d" 
  4: data-filter="true">

The data-role of listview tells the jQuery Mobile framework to use the jQuery Mobile Listview widget. Setting the data-inset attribute to true tells the jQuery Mobile framework to indent the list view and add the rounded edges. The data-theme attribute tells jQuery Mobile to use the dtheme. Setting the data-filter equal to true tells the jQuery Mobile framework to add the filter items text box up top. No additional work is needed to add the filter, it will search all of the ListItems that are part of this unordered list who’s data-role attribute is not set to list-divider for the text entered.

 

The List Divider

Adding the data-role of list-divider (Line 2 of the initial example) will make that list item appear as a divider.  You can use this attribute to group items, in my case, I grouped by date.

To establish the count bubble you will need to wrap the count of item around a span tag and give it the class of ui-li-count, as shown in Line 2.

Here’s an annotated image with markup.

image

The item in red is the individual list item which will be discussed in the next section.

The Items

Each sub item under the list divider needs to be it’s own Anchor element ( A )  wrapped in a ListItem (LI) tag as shown in lines 3-9 and 11-24 above.

  1: <li>
  2:     <a href="/m/e.aspx?Id=45">
  3:         <h3><span>Northwest Harvest at MVP Summit 2012</span></h3>
  4:         <p><strong><span>Northwest Harvest Warehouse</span></strong></p>
  5:         <p class="ui-li-aside"><span>from 11:30 AM to 5:00 PM</span></p>
  6:     </a>
  7: </li>

Each LI formatted above will generate a “row” as highlighted in the red boxed image above within your browser.  Clicking on one of those links will take you to the page specified in Anchor tag. In order to get the times to “float” to the left, you will need to use the ui-li-aside class.  Note, the > image will get added automatically by the framework.

Creating the jQuery ListView with an ASP.NET DataRepeater Control

In order to accomplish this, I went with a DataRepeater within a DataRepeater .  The first, or outside, DataRepeater (DateRepeater)will get a list of distinct dates from the data store in order to create the List Dividers. The second, or inner, DataRepeater (EventRepeater) will list all of the events for the day specified by the DateRepeater.

Let’s take a look at the code:

  1: <asp:Repeater runat="server" ID="DateRepeater" DataSourceID="EventDatesDataSource" OnItemDataBound="DateRepeaterOnItemDataBound">
  2:     <HeaderTemplate>
  3:         <ul data-role="listview" data-inset="true" data-theme="d" data-filter="true">
  4:     </HeaderTemplate>
  5:     <ItemTemplate>
  6:         <li data-role="list-divider"><%# Container.DataItem %>
  7:             <asp:Label runat="server" ID="EventCount" class="ui-li-count"></asp:Label>
  8:         </li>
  9:         <asp:Repeater runat="server" ID="EventRepeater" OnItemDataBound="EventRepeaterOnItemDataBound">
 10:             <ItemTemplate>
 11:                 <li>
 12:                 <asp:HyperLink runat="server" ID="EventUrl">
 13:                     <h3><asp:Label runat="server" ID="EventName" /></h3>
 14:                     <p><strong><asp:Label runat="server" ID="VenueName"></asp:Label></strong></p>
 15:                     <p class="ui-li-aside"><asp:Label runat="server" ID="EventDate"></asp:Label></p>
 16:                 </asp:HyperLink>
 17:                 </li>
 18:             </ItemTemplate>
 19:         </asp:Repeater>
 20:     </ItemTemplate>
 21:     <FooterTemplate>
 22:         </ul>
 23:     </FooterTemplate>
 24: </asp:Repeater>

In lines 2-4, using the HeaderTemplate property of the DateRepeater DataRepeater control I create the initial ListView. It is then closed in the lines 21-24 using the FooterTemplate of the DateRepeater DataRepeater control. Next in the ItemTemplate property (Line 6-8) of the DateRepeater DataRepeater control, I create a list divider by adding a ListItem (LI) with the data-role of list-divider with a label for the date.  Line 7 has a label control with a class of ul-li-count that holds the count of events that date.

Now within the ItemTemplate property of the DateRepeater DataRepeater control I also have another DataRepeater, EventRepeater. This DataRepeater will iterate through all the events for a day and create the individual ListItems (LI) for each event on that day (Lines 11-17). Notice how the ListItem is wrapped in an ASP:HyperLink control.  This will provide the hyperlink to the event details page.

That sums up creating jQuery Mobile listview using an ASP.NET DataRepeater control.

Converting an ASP.NET “Mobile” site to use jQuery Mobile

Building upon my previous post Introduction to jQuery Mobile, I wanted to share how I converted the Microsoft Global MVP Summit mobile site to use jQuery Mobile.

Getting Started

The first step was to look at the existing ASP.NET Master Page that the site was using and see where I had to make changes.  I included the skeleton mobile master page, prior to jQuery Mobile below.  Please note, I removed parts of the page that do not relate to the blog post.

  1: <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Mobile.master.cs" Inherits="MVPSummitEvents.Website.Mobile" %>
  2: 
  3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  4: <html xmlns="http://www.w3.org/1999/xhtml" >
  5: <head runat="server">
  6:     <title>MVP Summit Events - Mobile - </title>
  7:     <asp:ContentPlaceHolder ID="head" runat="server">
  8:     </asp:ContentPlaceHolder>
  9: </head>
 10: <body>
 11:     <form id="form1" runat="server">
 12:     <div id="mHead"><h1>MVP Summit Events</h1></div>
 13:     <div id="mMenu">
 14:         <asp:HyperLink runat="server" ID="hlMain" NavigateUrl="~/m/default.aspx" Text="Home" ToolTip="Home" /> | 
 15:         <asp:HyperLink runat="server" ID="hlMap" NavigateUrl="~/m/map.aspx" Text="Map" ToolTip="Map" /> | 
 16:         <a href="http://tinyurl.com/4e5mp5p" title="Windows Phone 7 App">Window Phone 7</a> App. |
 17:         <a href="http://itunes.apple.com/us/app/mvp-events/id416291827?mt=8">iPhone</a> App.
 18:     </div>
 19:     <div id="mBody">
 20:         <asp:ContentPlaceHolder ID="CphBody" runat="server">
 21:         
 22:         </asp:ContentPlaceHolder>
 23:     </div>
 24:     </form>
 25:     <div id="mFoot">Copyright ©2009-2012, <a href="http://www.josephguadagno.net" title="Joseph Guadagno">Joseph Guadagno</a> | <a href="http://twitter.com/jguadagno" title="Follow jguadagno">@jguadagno</a> | <a href="mailto:jguadagno@sevdnug.org">Contact</a></div>
 26: </body>
 27: </html>

Converting the document head

The first thing I needed to do was to update the DOCTYPE on line 3 to

  1: <!DOCTYPE HTML>

Next was to include the jQuery Mobile scripts and css files, after that my head section looked like this:

  1: <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Mobile.master.cs" Inherits="MVPSummitEvents.Website.Mobile" %><!DOCTYPE html> 
  2: <!DOCTYPE html> 
  3: <html xmlns="http://www.w3.org/1999/xhtml" >
  4: <head runat="server">
  5: 	<title>MVP Summit Events - Mobile - </title>
  6: 	<meta name="viewport" content="width=device-width, initial-scale=1"> 
  7: 	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
  8: 	<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  9: 	<script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
 10: 	<asp:ContentPlaceHolder ID="HeadContent" runat="server" />
 11: 	<link id="Link1" rel="stylesheet" runat="server" href="/css/m.css" />
 12: 	<script type="text/javascript" src="../js/analytics.js"></script>
 13: 	<script type="text/javascript" src="../js/analytics.jqmobile.js"></script>
 14: </head>

Again, I removed parts that are not required for this post.

You should notice that line 2 is now different and I added lines 6, 7,8,9 and 13.  Line 6 contains the viewport meta tag, the description from the jQuery Mobile docs is …

Note above that there is a meta viewport tag in the head to specify how the browser should display the page zoom level and dimensions. If this isn't set, many mobile browsers will use a "virtual" page width around 900 pixels to make it work well with existing desktop sites but the screens may look zoomed out and too wide. By setting the viewport attributes to content="width=device-width, initial-scale=1", the width will be set to the pixel width of the device screen.

Lines 7, 8, 9 contain the references to jQuery Mobile style sheet, the jQuery library and the jQuery Mobile library. Line 13, is a work around for using Google Analytics which is described here.

Converting the Document Body

Looking at the body of the Master Page, I was almost ready for the jQuery Mobile conversion.

  1: <div id="mHead"><h1>MVP Summit Events</h1></div>
  2:     <div id="mMenu">
  3:         <asp:HyperLink runat="server" ID="hlMain" NavigateUrl="~/m/default.aspx" Text="Home" ToolTip="Home" /> | 
  4:         <asp:HyperLink runat="server" ID="hlMap" NavigateUrl="~/m/map.aspx" Text="Map" ToolTip="Map" /> | 
  5:         <a href="http://tinyurl.com/4e5mp5p" title="Windows Phone 7 App">Window Phone 7</a> App. |
  6:         <a href="http://itunes.apple.com/us/app/mvp-events/id416291827?mt=8">iPhone</a> App.
  7: </div>
  8: <div id="mBody">
  9:     <asp:ContentPlaceHolder ID="CphBody" runat="server">
 10:     </asp:ContentPlaceHolder>
 11: </div>
 12: <div id="mFoot">Copyright ©2009-2012, <a href="http://www.josephguadagno.net" title="Joseph Guadagno">Joseph Guadagno</a> | <a href="http://twitter.com/jguadagno" title="Follow jguadagno">@jguadagno</a> | <a href="mailto:jguadagno@sevdnug.org">Contact</a></div>
 13: </form>

I have my Master Page broken up into a header, menu, body, and footer. All I had to do was assign the jQuery Mobile data-role attributes and I was done.  However I took this time to “tweak” the layout of the mobile site look more like it would on the iPhone and other mobile devices.  I still keep the header, but moved the menu to the footer section and moved the existing footer to an about page.  The new body of the mobile Master Page looks like this.

  1: <div data-role="page">    
  2:   <div data-role="header" data-theme="b"><h1><asp:Label runat="server" ID="HeaderLabel"></asp:Label></h1></div>
  3:   <div data-role="content" data-theme="b">
  4:     <asp:ContentPlaceHolder ID="BodyContent" runat="server">
  5:     </asp:ContentPlaceHolder>  
  6:   </div>
  7:   <div data-role="footer" data-theme="b">
  8:     <div data-role="navbar">
  9:       <ul>
 10:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/default.aspx" data-icon="home">Home</asp:HyperLink></li>
 11:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/map.aspx" data-ajax="false">Map</asp:HyperLink></li>
 12:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/Apps.aspx">Apps</asp:HyperLink></li>
 13:         <li><asp:HyperLink runat="server" NavigateUrl="~/m/About.aspx" data-icon="info">About</asp:HyperLink></li>
 14:       </ul>
 15:     </div>
 16:   </div>
 17: </div>

To me this seems quite readable and clearly identifies what each section (div) is responsible for.

Let’s break it down.

First all the previous DIV’s in between the FORM tags where placed within a

  1: <div data-role="page"></div>

tag. The next step was to convert each of the DIV’s that I had into a jQuery Mobile DIV. There is really no ‘jQuery Mobile DIV’ just an attribute that tells jQuery what “section” of the document this div is for.  I added the data-role=”header” to the DIV with the ID of mHead, I added the data-role=”content” to the DIV with the ID of mBody and I added the data-role=”footer” to the DIV with the ID of mFooter.

“Ok but what happened to the mMenu DIV” you ask.  Take a look at line 8 in the code sample above.  I moved the “menu” to the footer of the new document and assigned it a data-role of navbar. This is a jQuery Mobile widget that creates a simple menu of buttons out of all of the listitem elements of the unordered list. The data-icon attribute is an attribute that allows you to indicate one of the 18 built in icons for any jQuery Mobile button.

After this, I was done.  I now have a jQuery Mobile version of the Microsoft Global MVP Summit site that looks the same on virtually every mobile browser with little to no work.

Up next, how to convert other elements of an ASP.NET mobile site to use jQuery Mobile widgets.

Introduction to jQuery Mobile

Back in November I sat in on a session by Scott Hanselman on creating a mobile site on ASP.NET using jQuery Mobile.  While I was watching this session I could not stop thinking how easy is this, I can do this for the mobile version of the Microsoft Global MVP Summit mobile site. So like most of us, it took me a month to get to it.

A few days ago while on vacation and every one was asleep, I started to play around with jQuery mobile and in about an hour I had a sample site created.  Here’s how you can get started.

Getting started with jQuery Mobile

According the jQuery Mobile website, jQuery Mobile is…

A unified, HTML5-based user interface system for all popular mobile device platforms, built on the rock-solid jQuery and jQuery UI foundation. Its lightweight code is built with progressive enhancement, and has a flexible, easily themeable design

To get started with jQuery Mobile you can head over to their Quick Start Guide.  Here is the minimum HTML document that you need for jQuery Mobile.

  1: <!DOCTYPE html> 
  2: <html> 
  3: 	<head> 
  4: 	<title>My Page</title> 
  5: 	<meta name="viewport" content="width=device-width, initial-scale=1"> 
  6: 	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
  7: 	<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  8: 	<script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
  9: </head> 
 10: <body> 
 11: <div data-role="page">
 12: 	<div data-role="header">
 13: 		<h1>My Title</h1>
 14: 	</div><!-- /header -->
 15: 	<div data-role="content">	
 16: 		<p>Hello world</p>		
 17: 	</div><!-- /content -->
 18: </div><!-- /page -->
 19: </body>
 20: </html>

The first this you will notice is the simple DOCTYPE.

<!DOCTYPE html>

Next you will need to include a reference to the jQuery Mobile scripts and css files in the HEAD section of the document.

  1: <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
  2: <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
  3: <script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>

And then finally in your HTML Body, you need to create a “page”. You do this by creating a DIV and an assigning the role of page to it.

  1: <div id="#default" data-role="page">
  2: ...
  3: </div>

The id is optional and can be used to have more than one page within a document.  For more on the page structure, check out the Anatomy of a Page in the jQuery Mobile docs.

That’s all you need for the bare minimal jQuery Mobile page.

jQuery Mobile Page Parts

jQuery Mobile pages are made up of potentially 3 parts; the header, the content (body) and the footer.  These parts are outlined by creating a div and assigning a role to it.  The roles are data-role=”header”, data-role=”content”, and data-role=”footer”.

  1: <div data-role="page"> 
  2: 	<div data-role="header">...</div> 
  3: 	<div data-role="content">...</div> 
  4: 	<div data-role="footer">...</div> 
  5: </div> 

Header Part

Is defined by following markup.

  1: <div data-role="header">...</div>  

The header part of the document is where you place content that you want as the head or beginning part of the page. This is typically page titles and toolbars.

Content Part

Is defined by following markup.

  1: <div data-role="content">...</div>  

The content part of the document is where you place the page content.

Footer Part

Is defined by following markup.

  1: <div data-role="footer">...</div>  

The footer part of the document is where you place the footer content. This is typically navigation, copyright information, etc.

Hopefully, I armed you with enough information to get started with jQuery Mobile.  In the next few posts I will talk about how I converted the Microsoft Global MVP Summit mobile site to use jQuery Mobile.

About the author

Joseph Guadagno Name: Joseph Guadagno
Occupation: Programmer, Vice President of INETA North America, President of SEVDNUG, Microsoft Visual C# MVP
Location: Chandler, AZ

Joseph Guadagno RSS Joseph Guadagno Twitter Joseph Guadagno Linked In

Advertisements

Microsoft Application development contest