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: "https://blogs.msdn.com/shahpiyush" },
{ FirstName: "Jon", LastName: "Gallant", Url: "https://blogs.msdn.com/jongallant" },
{ FirstName: "Scott", LastName: "Guthrie", Url: "https://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: "https://blogs.msdn.com/shahpiyush", SpendingBudget:1.50},
{ FirstName: "Jon", LastName: "Gallant", Url: "https://blogs.msdn.com/jongallant", SpendingBudget: 1000.99 },
{ FirstName: "Scott", LastName: "Guthrie", Url: "https://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: "https://blogs.msdn.com/shahpiyush" },

            { FirstName: "Jon", LastName: "Gallant", Url: "https://blogs.msdn.com/jongallant"},

            { FirstName: "Scott", LastName: "Guthrie", Url: "https://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.