AJAX, ASP.NET, C#, Visual Studio, Web Services

Client Side Template AJAX Control

Since the release of ASP.NET AJAX it’s been relatively easy to update portions of a page with new data from the server without performing a full page post back.

Place any grid in an UpdatePanel and voila you have a nice AJAX style grid… but is this really a good thing? Sure it’s easy, but that doesn’t make it “good”. UpdatePanels are great for small chunks of data, but not so good for larger amounts of data (like grids etc).

How do you fix this problem? Well, you could ask the server for some JSON and parse it yourself, loop through a set of elements and update them using JS. This method performs very well… but comes at the cost of difficulty and code complexity. It would also be hard to maintain.

What about a way to get the best of both worlds. Client side controls that use JSON data from the server (so no markup is sent to client after initial load) and easy to use!

Thanks to Nikhil Kothari I had a cool idea to allow an easy implementation of client site templating.

<Sample Code>

http://www.webjak.net/files/FileDetail.aspx?fileId=af820273-6a56-47a2-8f70-eb9dea4a4f34

</Sample Code>

<Live Example>

http://dev.webjak.net/ClientTemplateControlExample/

</Live Example>

Check out the example site! How fast is it?? Load up Firebug or something and test it out for yourself!

Introducing the ClientTemplateControl

The ClientTemplateControl is an ASP.NET AJAX Client Control. It works very similar to the DataList in ASP.NET. Create an item template with markup and bind attributes to data elements. Then assign a datasource to the control and bind it. The control will then take care of iterating through the data source, repeating the item template for you.

When you reload the data, for example after paging – the ClientTemplateControl detects that the elements are already added to the page and REUSES THEM! That’s right, it uses the template to whip through and only update their attributes etc! This means no setting of innerHTML etcetera on a refresh! Well, except where your template “bindings” set innerHTML (like in spans etc).

This HTML DOM reuse means that there is absolutely no flicker either… and there is no DOM rendering time on large lists… just the time it takes to go through and update attributes etc… this is very fast.

To bind an attribute, use the { and } to delineate a bound attribute. The control detects { and compiles the attribute text in to a function, which is then run, passing in the current data context (the current row from the data source and a few other parameters).

Example

This will write out the value in dataContext.Surname into the title:

<span title="”{return">Some Span</span>

To set innerHTML etc, which don’t have attributes you can use the “this” JavaScript keyword.

Example

This will write out the value in dataContext.Surname into the title and innerHTML:


<span title="”{this.innerHTML"></span>

You might want to alternate color between odd and even rows.

Example

Note here I am using title to set the style. You could use any parameter you like. Note also that title above does not return anything. This is fine, and will result in an empty title attribute.

<div title="{this.style.backgroundColor=pageRowIndex % 2 == 0?'lightblue':'#eeeeee';}">rest of the template</div>

. pageRowIndex is another parameter passed into the functions by default.

There is a special circumstance when working with anchors and images. “src” and “href” don’t like the special “{}” syntax. You can still set href and src, just do it using the “this.” syntax.

Example

<img style="border:none;" title="{this.src='ImageLoader.ashx?id=' + dataContext.ProductID;}" />

Getting data in

Providing data to the control is very easy. You may want to get some JSON data from a webservice and bind to the control in pages.
Note: Pagination is not handled by the control, so only return the data for a single page at a time from the server.

E.g. getting data from a AJAX-enabled WCF service is easy!

AdventureWorksService.GetProducts(page,$get("pageSize").value,endGet);

function endGet(result)
{
	c.set_itemsSource(result);
	c.dataBind();
}

How easy is that?!

The “result” variable above lives in the WCF service as List<AWProductBusinessObject>, thus serialising as an array of AWProductBusinessObject to JSON. AWProductBusinessObject looks like this:


[DataContract]
public class AWProductBusinessObject
{
	 [DataMember]
	 public int ProductID { get; set; }
	 [DataMember]
	 public string Name { get; set; }
	 [DataMember]
	 public string ProductNumber { get; set; }
	 [DataMember]
	 public string Color { get; set; }
	 [DataMember]
	 public decimal StandardCost { get; set; }
	 [DataMember]
	 public decimal ListPrice { get; set; }
	 [DataMember]
	 public decimal? Weight { get; set; }
	 [DataMember]
	 public int DaysToManufacture { get; set; }
	 [DataMember]
	 public DateTime SellStartDate { get; set; }
	 [DataMember]
	 public DateTime ModifiedDate { get; set; }
	 [DataMember]
	 public Byte[] SmallImage { get; set; }
	 [DataMember]
	 public Byte[] LargeImage { get; set; }
}

I’ll leave the rest of this detail to the sample code.

Something interesting in the control is that it caches the evaluated functions from the “bindings” so they are only evaluated on the creation of the first instance of the template on the first page. That’s right, only the very first record on the first page has this overhead, all other items on that page (say you have 10 records, 9 will use the cache) and all other page refresh items (10 from 10 on subsequent refreshes) will use the cache and be very fast.

Note: Code does not check for the last page in the data… it will just keep paging into oblivion 🙂
Note: You may have noticed every time I write “bind” or “binding” it’s in quotes. This is because it’s not real binding… it just chose to call it that because it was familar 🙂
Note: This has no relation to the ASP.NET AJAX Futures databinding feature.
Note: This is by no means W3C compliant – so don’t bother commenting about it – unless that is you can find a way to upgrade it to make it W3C compliant 🙂
Note: This code has been tested with Firefox 2 and 3, Opera 9.5, IE 7 and Safari 3.1.2.

4 thoughts on “Client Side Template AJAX Control

  1. Hey,

    You can do it however you like… but JSON is hands down the best option for JS integration… WCF can output JSON <- have a search around, you’ll see plenty of cool stuff.

    For a more supported version of client side templating keep an eye on ASP.NET 4 which is floating around on the MS download sites and there are plenty of blog posts on this since PDC.

    Cheers,

    Jordan.

  2. I know it can output JSON natively but I’m bit more comfortable with XML and String outputs from WCF and was thinking before I actually use your control that it would work with them without any additional work.

    I was thinking to use .NET 4.0 client side templating but since it’s still half-baked I guess so I’m avoiding it for any production site yet.

    Thanks

    -Zubair

  3. The problem with XML is that it’s not supported natively in the browser… also you have the “tag tax” – tags create extra data cost which is not a problem with JSON (very little overhead).

    Using native strings is fine if you like… but I’d steer clear of manually parsing strings if it where me 🙂

    Cheers,

    Jordan.

Comments are closed.