ASP.Net AJAX 4.0 Client Templates in depth


The best way to know a Javascript library is to pry open the javascript file and look at the details. This release has a lot of powerful features which I will discuss here.


1.   Sys.Observer – Ajax 4.0 includes an implementation of Observer Pattern. In plain words you can use this pattern to have a publisher/subscriber scenario, wherein if any property on the publisher changes all the subscribers are notified. Dave Reed has a great article which goes in depth about this pattern. The other features mentioned below use this pattern a lot internally. Here is an example on how to use this object –


                 var product = { name: “Foo Choclate Bar”, price: 1, inStock: true }



var
productsPublisher = Sys.Observer.observe(product); //The publisher which is being observed



Sys.Observer.addPropertyChanged(productsPublisher, productSubscriber); //Add a subscriber for any property change on the publisher



productsPublisher.setValue(“inStock”, false); //Change a property



function
productSubscriber(product, eventArgs) //Subscriber


{


    if (eventArgs.get_propertyName() == “inStock” && product.inStock == false) {


        alert(“The product is out of stock”);


    }


}


 


2.   Sys.Ui.Templates or Client Side Templates – I think of this feature as a Client side repeater version of the classic ASP.Net server side repeater. Using this feature you can bind data to a defined template and it iterates through the data and renders it using the contents defined inside the template. An example of a template is –


<div id=”authorsTemplate” style=”visibility:hidden;display:none;“>
    <ul>
        <li>First Name: {{ FirstName }}</li>
        <li>Last Name: {{LastName}}</li>
        <li>Url: <a href=”{{Url}}”>{{Url}}</a></li>
    </ul>
</div>


1.   Data which needs to be binded to a template are enclosed within {{<data>}}, e.g. {{ FirstName }}. The above template will be repeated and displayed if you loop through your data and instantiate the templates. Notice the style is made to hide this template so it is not shown to the user on load.


2.   Create a div where the above template will be rendered.
<div id=”targetdiv”></div>


3.   To register this template with Sys.Ui.Template you pass the template Id to the constructor –
var template = new Sys.UI.Template($get(“authorsTemplate”));


4.   To create an instance for each data row in your collection you need to call the “instanceIn” method –


template.instantiateIn($get(“targetdiv”), <jsondata>);


“targetDiv” is the place where you need this template to be rendered.


 


Here is the snapshot of the example –


<script>
    var bloggers = [{ FirstName: “Piyush”, LastName: “Shah”, Url: “http://blogs.msdn.com/shahpiyush” },
            { FirstName: “Jon”, LastName: “Gallant”, Url: “http://blogs.msdn.com/jongallant” },
            { FirstName: “Scott”, LastName: “Guthrie”, Url: “http://webblogs.asp.com/scottgu”}]



    function LoadTemplates() {
        var template = new Sys.UI.Template($get(“authorsTemplate”));
        for (var i = 0; i < bloggers.length; i++) {
            template.instantiateIn($get(“targetdiv”), bloggers[i]);
        }
    }
</script>


<body onload=”LoadTemplates()”>
<div id=”authorsTemplate” style=”visibility:hidden;display:none;“>
    <ul>
        <li>First Name: {{ FirstName }}</li>
        <li>Last Name: {{LastName}}</li>
        <li>Url: <a href=”{{Url}}”>{{Url}}</a></li>
    </ul>
</div>
<div id=”targetdiv”></div>
</body>


 


3.   Markup Extensions – Using this feature you can create expressions. The syntax for using it is –
{expressionName, defaultValue, parameterName1=parameterValue1, parameterName2=parameterValue2[, …]}  
Here is an example of a number to currency conversion expression I wrote.


1)    First register the markup extension –


Sys.Application.registerMarkupExtension(“formatCurrency”,
  function(component, targetProperty, properties) {
      var value = + properties.value;
      var numArray = value.split(‘.’);
      var decmal = numArray[0];
      var cents = numArray.length > 1 ? ‘.’ + numArray[1] : ;
      var rgx = /(\d+)(\d{3})/;
      while (rgx.test(decmal)) {
          decmal = decmal.replace(rgx, ‘$1’ + ‘,’ + ‘$2’);
      }
      return (“$” + decmal + cents);
  }
);


2)    You can now use the markup in your template like this – {formatCurrency “US”, value={{number}}}


3)    Let’s update the above example of the data to be like this –


var bloggers = [{FirstName: “Piyush”, LastName: “Shah”, Url: “http://blogs.msdn.com/shahpiyush”, SpendingBudget:1.50},
            { FirstName: “Jon”, LastName: “Gallant”, Url: “http://blogs.msdn.com/jongallant”, SpendingBudget: 1000.99 },
            { FirstName: “Scott”, LastName: “Guthrie”, Url: “http://webblogs.asp.com/scottgu”, SpendingBudget: 1000000.00}]


4)    Update the template to be like this –


<div id=”authorsTemplate” style=”visibility:hidden;display:none;“>
    <ul>
        <li>First Name: {{ FirstName }}</li>
        <li>Last Name: {{LastName}}</li>
        <li>Url: <a href=”{{Url}}”>{{Url}}</a></li>
        <li>{formatCurrency “US”, value={{SpendingBudget}}}</li>
    </ul>
</
div>



  1. Declarative Instantiation – In simple terms this allows you to create controls or behaviors by putting a certain markup in the container instead of creating a full xhtml markup. Here is an example this syntax attaches a Dataview (which I will go over next) to a div without –

1.   Register the namespace in the body. This is similar to Registering a user control in ASP.Net
<body xmlns:sys=”javascript:Sys” xmlns:dataview=”javascript:Sys.UI.DataView” sys:activate=”*” >
Here we are first registering “Sys” with “sys” and “Sys.Ui.Dataview” with “dataview”.
sys:Activate attribute specifies which ID’s of elements to activate. A “*” means any Id with sys:attach (seen shortly) will be activated.


2.   To activate the dataview in any html element you need to do this –


<div sys:attach=”dataview” dataview:datasource=”<jsondata>”>



</div>

Here we are first attaching the “dataview” to the div and since sys:activate=”*” which means that on load it will be activated. I am also setting the datasource property on the dataview.


 



  1. Sys.UI.DataView– This control allows you to Bind data (one way or read-only) to your client templates. It hides the complexity and extra markup I had showed in creating templates above. To show how easy it is to create client templates using Dataview check out the example –


<body xmlns:sys=”javascript:Sys” xmlns:dataview=”javascript:Sys.UI.DataView” sys:activate=”*”>


<script>


    var bloggers = [{ FirstName: “Piyush”, LastName: “Shah”, Url: “http://blogs.msdn.com/shahpiyush” },


            { FirstName: “Jon”, LastName: “Gallant”, Url: “http://blogs.msdn.com/jongallant”},


            { FirstName: “Scott”, LastName: “Guthrie”, Url: “http://webblogs.asp.com/scottgu”}]       


</script>


<div id=”authorsTemplate” sys:attach=”dataview” dataview:data=”{{bloggers}}”>


    <ul>


        <li>First Name: {{ FirstName }}</li>


        <li>Last Name: {{LastName}}</li>


        <li>Url: <a href=”{{Url}}”>{{Url}}</a></li>


    </ul>
</
div>


</body>


 


In my future post I will be showing how to do a 2 way binding using Client Templates.


 


 

Comments (8)

  1. Great MIX09 talk on ASP.NET AJAX 4.0. Stephen Walther is a really great presenter. I’m not an AJAX expert,

  2. I assume the new CDN is based on some of the items you described. Is there a listing of other items besides the one you discussed?

    System.UI.? for example.

    Are these (*.js files) found in the URL of the CDN?

  3. Paul Allies says:

    How would you bind subitems of the json object to an html element.

    For example, if one of the blogger items had a sub collection of hobbies. How would you loop/enumrate through these?

    I’ve tried {{Hobbies.name}} and it does not work.

  4. Sathyan says:

    Hi Piyush,

    How to make it a nested client template? where in i fetch more data for each of the parent data elements when i scroll over the parent element? In other words can i make a call to the dataview and bind it on a particlaur event and not ion page load?

  5. jason harper says:

    Hello there.  I’m finding that the ASP.Net wire format for MVC (to support complex types/arrays/etc) requires a syntax like MyComplexType[0].MyProperty.  Trying to use that syntax in an asp 4 client template such as:

    <input type="text" name="ContactAddresses[{{Index}}].City" id="ContactAddresses[{{Index}}].City" value="{{City}}"/>

    does not work.  Only the value gets populated, while the Id and name do not.  Seems the brackets mess up the token replacements.  Any idea how to solve this?  

  6. sid says:

    I just have a simple question which is from where do I download this library?

    Another question: Suppose I am writing a pure ajax application – meaning zero ASP.NET server-side code. Thus, I don't have ScriptManager etc. Can this library be used in this scenario?

  7. Absolute newbie says:

    is there a simple way to integrate in the website(!) something like an if statement? Example: if firstname equal to Scott should the firstname be displayed in green, in all other cases should the firstname been displayed in black … knowing that we must surround the {{ FirstName } } with somthing like a < d i v style="color=  … {{ FirstName } } </div>

    Thx in advance!

  8. Jquery developer says:

    Is this better than Jquery Templates in terms of performance?