Using the ASP.Net MVC & Jquery Template to repeat a HTML Fragment

Saturday, October 23, 2010

I have been playing around with the new jQuery Template plugin and I’ve got to say that I am pretty impressed. I haven’t seen too many code samples so I thought I would share my approach as I had some somewhat sophisticated requirements that I haven’t really seen covered anywhere.


The repeating HTML is pretty busy so I wanted to isolate it because if it ever changes I could just publish an HTML file instead of doing a build or even republishing the view. (We use a CMS system that makes publishing content pretty easy to do.) I also wanted to reuse the fragment in different views while keeping things DRY (Don’t Repeat Yourself) at the same time. 

To do this, I created an HTML Helper that reads the HTML fragment caches it and renders inside the JavaScript tag. So this is my HTML tag:

   1: <li>
   2:     <div style='float: left;'>
   3:         <img style='border: 0px none; width: 200px;' alt='${Name}' src='${TopImagePath}'>
   4:     </div>
   5:     <div style='margin-left: 210px;'>
   6:         <div style='padding: 5px;'>
   7:             <b>
   8:                 <a href='/Activities/Activity/Detail/${Code}/'>${Activities}</a>
   9:             </b>
  10:         </div>
  11:         {{html ShortDescription}}<br>
  12:         <b>Duration:</b> ${Duration}<br>
  13:         <b>Code:</b> ${Code}<br>
  14:         <b>Level:</b> ${Level} <br>
  15:         <b>Activity Types:</b> ${Types}<br>
  16:         <b>Activity Level:</b> ${Level}<br><b>Price:</b> $<br>
  17:     </div>
  18: </li>

I’m going to move the styles to a CSS file, but you get the idea. This HTML is sitting in a content folder off the root of the website, and the name of the file is ActivityItem.htm.

Notice that the placeholders are designated as ${fieldName}, and if I want to encode the HTML, I could use the placeholder {{html fieldName}}.

I then render the HTML in the JavaScript tag. The JavaScript tag has an id that will referred to by jQuery Template plugin and also uses the specific type “html/text” so it does not force a syntax check from the JavaScript engine or display it prematurely in the browser.

   1: <script id="activityItemsTemplate" type="text/html">
   2:     <%= Html.RenderPath("Controls/activityItem.html") %>
   3: </script>


The only thing the RenderPath HTMLhelper does is get the HTML content from cache, and if it is not there; it reads the content from the HTML file, and adds back to cache, and renders it. The caching is nothing fancy. Its just the common caching technique used forever it seems like.

When the HTML Helper renders the content from cache the the JavaScript tag looks like this.

   1: <script id="activityItemsTemplate" type="text/html">
   2:     <li>
   3:     <div style='float: left;'>
   4:         <img style='border: 0px none; width: 200px;' alt='${Name}' src='${TopImagePath}'>
   5:     </div>
   6:     <div style='margin-left: 210px;'>
   7:         <div style='padding: 5px;'>
   8:             <b>
   9:                 <a href='/Activities/Activity/Detail/${Code}/'>${Activities}</a>
  10:             </b>
  11:         </div>
  12:         {{html ShortDescription}}<br>
  13:         <b>Duration:</b> ${Duration}<br>
  14:         <b>Code:</b> ${Code}<br>
  15:         <b>Level:</b> ${Level} <br>
  16:         <b>Activity Types:</b> ${Types}<br>
  17:         <b>Activity Level:</b> ${Level}<br><b>Price:</b> $<br>
  18:     </div>
  19: </li>


Now all I have to do is make an AJAX call to get the JSON collection object and map it to the template.

   1: $.getJSON(url, { Prices: prices, Levels: levels, Experiences: experiences, currentPage: currentPage, pageSize: pageSize }, function (data) {
   3:     var list = data.ActivityList;
   5:     var markup = $("#activityItemsTemplate").html();
   7:     $.template("activityItemsTemplate", markup);
   8:     $.tmpl("activityItemsTemplate", list).appendTo("#activityItemsContainer");
   9:     }
  10: });


The Container is just the ID of the UL tag.

   1: <ul id="activityItemsContainer">       
   2: </ul>
Hope that helps

comments powered by Disqus