Building a Solid Ajax Effect (Part 1)

Much is made about Ajax these days, and why not, when used properly it can effectively elevate your user experience to new levels and keep customers comings back. Furthermore, if you follow the principles of Ajax you can use to increase the availability of your site and its presentation by reducing load on the server thus giving the impression of a highly responsive website.

However, as with any good thing, its no silver bullet.  Improperly using Ajax and/or not understanding how users will interact with your site can drive them away as well. In a recent post, I highlighted the three tenants of Ajax: 1) Less is More, 2) Instant Feedback, 3) Synchronization.  I think its important, whenever developing a user experience that will rely on Ajax, to consider how your code deals with these tenants.  Recently, I added a means to support a many-to-many relationships for my data model using a pretty slick combination of MVC and JQuery and I decided to walk the process of how I validated the tenants.

So lets start with some background information.  My object model consists of three entities: 1) A series entity, 2) a genre entity, 3) a relationship object that supports a series and genre reference and the weight of that entry with respect to the series.DataModel

Lets briefly cover some of our goals for this process:

  1. The user should be able to easily and quickly add “n” Genres to the list
  2. The user should be able to easily delete the entries from the list
  3. The presence of an existing series ID may not be available if we are inserting
  4. We would like to keep all data pertaining to the base entity on the page (basically, we shouldn’t have to use two pages for this operation)

A few notes on the outcome of this effect:

  • We will not enforce distinctness for the entries on the client
  • We will not cover micro-linking a quick add (that will be later)

So some things to see right off the bad.  A web service to update things on the fly will not be acceptable due to condition 3.  We do not wish to duplicate HTML so we should try to use the same block container to reduce code duplication, this to me suggests well need a partial view.  So before we start trying to add our Ajax effect lets get the basics of the form, here is what mine looks like: InitialInterface2

This is very basic, I wont bother explaining it. So this is where we get to be creative and decide how we want to display this to the user.  Remember that we need to allow them to select a single genre (drop down list) and they need to be able to provide a weight. Now we could use a simple text box for them to enter a value, however, I would like to give the interface some zest so I will be using JQuery UI’s Slider control.  Below is my interface, note that I manually added a genre to test the initial load look and feel:

InterfaceWithGenres
(you will not see the slider position preset, this is done in part 2 via JavaScript)

So in this version I have added a dropdown containing all the available genres in the system.  The slider permits the user to easily choose a weight value for the genre as it relates to the series we are editing.  I have also added a delete image to the left of the drop down that we will wire up later.  Also I added a link for adding new genres inline.  Now here is the code for the Genres section:

   1:  <div id="genreContainer">
   2:          <%
   3:              foreach (var item in ViewData.Model.SeriesGenres)
   4:              {
   5:          %>
   6:              <div style="float: left;" class="genreSelect">
   7:          <% Html.RenderPartial("Series/GenreSelect", item, ViewData); %>
   8:              </div>
   9:              <br style="clear: both;" />
  10:          <%
  11:              }
  12:          %>
  13:      </div>
  14:      <a href="#" id="addGenre">Add Another Genre</a>

There is quite a bit going on here, some of which involves MVC and the magic it brings and thus an in-depth explanation of is outside the scope of this post so I will be brief in my summary of these things.

The first thing to look at is Line 2, simply know that ViewData.Model refers to an instance of the Series entity.  Thus we are iterating over each of the existing relationships and passing it to the partial view we are reading on Line 7.  The RenderPartial method allows us to include HTML from an existing View in a “parent” view.  It allows us to define the model that that “partial view” will use along with a ViewData object, so we pass both of these to the partial view.  The path to the partial view is a specific format relative to the folder in Views named for the Controller the Views directly belong to (its an MVC thing).

The following HTML/ASP .NET is found in the partial view:

   1:  <div style="float: left; margin-left: 10px; margin-right: 10px;
   2:      padding-top: 5px;">
   3:      <img src="../../../Content/images/00498f_11x11_icon_close.gif"
   4:               class="removeGenre" alt="Remove Genre" />
   5:  </div>
   6:  
   7:  <div style="float: left; margin-right: 10px;">
   8:      <%= Html.SelectBox("genres", (List)ViewData["Genres"],
   9:                           ViewData.Model.GenreId.ToString()) %>
  10:  </div>
  11:  
  12:  <div style="float: left; padding-top: 4px;">
  13:      <div class="slider" style="width: 200px;">
  14:          <div class="ui-slider-handle">
  15:          </div>
  16:      </div>
  17:  </div>
  18:  <div style="float: left; margin-left: 10px; padding-top: 3px;"
  19:          class="sliderLabel">
  20:      <%= ViewData.Model.Weight.ToString() %></div>
  21:  <%= Html.Hidden("weights", ViewData.Model.Weight.ToString(),
  22:                    new { @class="sliderValue" }) %>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

As you can see, we make full use of a variety of HTML helpers (note that SelectBox is a custom one that I wrote).  Notice how we use the ViewData.Model here to fill in and pre-select values.  Also, its very important to understand why we are using classes and names.

If you look at this code and remember the context it is being called in you will see that every drop down for genre selection is named: genres.  In fact, you will see that within this effect there are a lot of elements that share names and classes.  This will be crucial when it comes to access our data in the MVC controllers and from JQuery.

So with this we created a clean view that contains no JavaScript and properly loads our existing Genre relationships.

In Part 2, we will cover wiring up the basic effects using JQuery.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Advertisements

One thought on “Building a Solid Ajax Effect (Part 1)

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