Loading Client Side Templates in Angular JS

One of the features of Angular JS is client routing. This enables us to create single page applications (SPA) by which our site loads an initial html page and every subsequent page is brought in dynamically without triggering a full page refresh.

I was giving a presentation on Angular recently and someone in the audience asked if the templates where downloaded when the web app started, or dynamically as the user navigates to a specific page. This is a great question because on a complex multi-page site, you don’t want to load the templates upfront.

So I decided to investigate. Fortunately, this was an easy thing to do using the Chrome Dev Tools. As part of my talk I built a small sample app called Tweet Save. This web app allows you to search twitter and then bookmark tweets you like. You can see it’s source on github.

The saved tweets page relies on a template called “SavedTweets.html.” Inspecting the network tab on initial load doesn’t show any reference to SavedTweets.html. After clicking the link to the saved tweets page I see the following in my dev tools:

Dev tools

The template is only loaded when the user requests that route from my route provider. If navigate back to the initial search page, then again to saved tweets the two files above will not be downloaded again. That’s because at this point, angular already has the template it needs for that route.

so there we have it. Angular only loads html templates on demand when a user requests that specific route.

Advertisements

Nested Directive Virtual Groups in Angular JS

In my last post I went over a new unreleased feature of Angular JS, Directive Virtual Groups. This allows you to append -start to a directive allowing it to span multiple DOM elements. You can terminate the multi-DOM element by applying -end to the same directive. For example:

<tr ng-repeat-start="order in orders">
  <td>{{order.description}}</td>
</tr>
<tr ng-repeat-end>
  <td>{{order.number}}</td>
  <td>{{order.price}}</td>
</tr>

This would iterate over a series of orders and render two TR tags for each order. The ng-repeat-start indicates the ng-repeat condition as well as a starting flag for angular. Everything following that (including it’s TR tag) is part of the template, until it reaches a ng-repeat-end. That element is then included and is considered the terminating element.

Well what about multiple -start and -end tags nested? I decided to try to play around with ng-click in addition to ng-repeat. Imagine if we wanted to make only the number and price table cells clickable. We want those cells to call a function named ‘calculate’. I could easily modify the above example to be:

<tr ng-repeat-start="order in orders">
  <td>{{order.description}}</td>
</tr>
<tr ng-repeat-end>
  <td ng-click-start="calculate(order)">{{order.number}}</td>
  <td ng-click-end>{{order.price}}</td>
</tr>

While this may seem complicated, the syntax basically says

  1. start the repeat process at the first TR tag
  2. terminate the template at the second tag (where ng-repeat-end) comes in
  3. In the second TR tag, start defining a clickable region ng-click-start
  4. Apply click region to first and second TD until ng-click-end is found

Notice how I only defined the target of the ng-click once, but both elements are now clickable and will call the calculate method. Pretty cool and DRY!

As a reminder, this feature is in the code base but has NOT made it to the stable release of Angular. So it might not work for you unless you have the latest build form their Github repository.
works on my machine

Angular JS Directives – Repeating over multiple elements

I was watching a video from NDC featuring a cage match between Ember JS and Angular JS. Tom Dale and Rob Connery both did a good job of representing Ember and Angular respectively. At one point, Tom showed a feature of handlebars (which Ember uses for templating) that allowed him to iterate over a javascript array and for each element render out two html TR (table row) tags. This is easy to do in Ember because handlerbars uses a #each template and you can basically put anything you want between #each and /each like so (tom’s code from the talk follows):

{{#each orders}}
  <tr>
    <td>{{description}}</td>
  </tr>
 
  <tr>
    <td>{{number}}</td>
    <td>{{currency price}}</td>
  </tr>
{{/each}}

The result is something that looks like this (screenshot from the video):

Ember JS each example

So for each item, show the description on one line and the number and price (formatted as currency) on the next line. Pretty standard stuff for simple tabular data.

When it came time for Rob to offer rebuttal and duplicate this with Angular, he struggled and I don’t blame him. Even though I’ve done a bit of Angular and given presentations on the topic, while watching this I was stumped. You see Angular has an ng-repeat directive that allows you to iterate over a collection, much like #each. However, ng-repeat is applied to a DOM element and that element itself is used as the template for every item. To illustrate, check out this simple ng-repeat example:

<tr ng-repeat="order in orders">
  <td>{{order.description}}</td>
  <td>{{order.number}}</td>
  <td>{{order.price}}</td>
</tr>

Here we ask angular to iterate over all “orders” and for each iteration place the current item in a variable called “order”. The TR tag itself will be used as a template and anything inside of it will be part of that template also. The problem now is how do you extend this to multiple TR tags like Tom did in the Ember example? It’s not something I had seen before. So I decided to do some research and see if there was in fact a way to do this in Angular.

I came across a few posts that talked about adding the ability to use ng-repeat in an html comment (similar to how Knockout JS bindings can be used in comments), but the Angular lead turned that proposal down. I then found this page on Angular’s Git hub Page. It talks about a new feature of Angular, Directive Virtual Groups. This exactly what I needed ! 🙂

So how does it work? In a nutshell it’s a way to have a directive span over multiple elements by indicating a start and end. This is done by simply appending -start and -end to the directive itself. It’s actually a very nice way of doing this as it extends existing directives.

Unfortunately this isn’t the stable release of Angular, but it’s good to know that this feature is in the code base and is coming. So to play around with it I had to download the  Angular source code and build it on my machine. After that I used the newly built angular.min.js file in a sample application and I was able to write code like this:

 <tr ng-repeat-start="order in orders">
    <td>{{order.description}}</td>
  </tr>
  <tr ng-repeat-end>
    <td>{{order.number}}</td>
    <td>{{order.price}}</td>
  </tr>

This new sytax allows us to take the repeat binding and extend it over two html elements, or any number of elements between -start and -end. If I included a 3rd row in between those TR’s, it would rendered as well.

I think this is a great addition to the framework and I love how it’s implemented as an extension to directives and really highlights the good architecture and separation of concerns you can get. Directives are complicated, but what they do offer is a clean way to isolate functionality and to build reusable components that can be composed on a page, giving the application developer greater power and flexibility

Knockout JS @ The San Francisco .NET Developers User Group

Last night I presented at the San Francisco .NET Developers User Group on Knockout JS with ASP.NET MVC4 and Web API. I had a great time there and I wanted to thank everyone for inviting me to speak to the group.

Here are my slides from the presentation.

Here is the Contact List application we built.(Please note that the demo expects SQL Server express to be running. If you want to use another version of SQL Server, then you just have to add a connection string in Web.Config that matches the name of the data context.)

You can find Knockout JS demos and examples here:
http://knockoutjsdemo.apphb.com/

The official Knockout JS website is here:
http://knockoutjs.com/

Additional Resources:
Knock Me Out – This is a great blog by one of the contributors to Knockout JS. Lots of material is covered.

Web API Serialization
Web API Paging and Filtering

sf-net

SLO .NET User Group Talk

Later today I’ll be speaking at the San Luis Obispo .NET User group. I’ll be presenting on Knockout JS, a powerful MVVM library for JavaScript. Knockout makes building interactive rich UI’s a lot of fun! I hope to see you there.

If you do attend, I ask that you please rate my talk so I know how I’m doing 🙂

Here are the slides and demos

Slides

Demo Source Code  – Play with the Demos Online

Here’s a few useful links about Knockout JS

Knockout Links

Learn Knockout Js – An excellent interactive tool for learning about Knockout JS

Knockout Me Out – A great blog about Knockout JS

SoCal Code Camp San Diego 2011

This past weekend I attended the SoCal Code Camp in San Diego and I had a blast. I gave 5 talks on mvc related topic and attended several great sessions. It was a fun experience and I truly enjoy going to Code Camp, it’s a great place to learn about new technologies and hang out with other fellow developers and friends.

Here are the slides and code samples from my talks:

The Microsoft Ajax Library

I’m a big Fan of the new new Microsoft Ajax library. It combines what was previously Asp.net AJAX and the Ajax Control toolkit into one library. As an added bonus, the new library contains a client side only version of all the controls in the control toolkit. So that means you can use any of the ui enhancements in asp.net mvc pages and really any web based framework.

The library is still in beta, but it’s already showing great promise.

In this post I’m going to be going over some customization features of the client side calendar control. You can read the basics about using the calendar control here .

The first issue we are going to tackle is how to set the date format. By default the calendar control returns a string with the format “MM/dd/yyyy”. However, this may not work for all locales and fortunately the control is configurable. We can easily change the format by calling the set_format function and passing in the desired format.

Sys.require(Sys.components.calendar, function () {
    var calendarControl = Sys.create.calendar("#travelDate");
    calendarControl.set_format("dd/MM/yyyy");
});


Now when you select a date it should show up in the dd/MM/yyyy format. Selecting December 6th, 2009 in the calendar now returns the string “06/12/2009”.
ajax-library-ddmmyyy

The second calendar feature I’d like to go over is how to use an html button to show the calendar. It’s actually quite simple and basically you just have to add an onclick handler to the button. Then in the handler function call the controls show() method. Let’s expand on our previous example and add a “Show” button.

First lets add the html markup:

<input id="travelDate" />
<input type="button" onclick="showCalendar()" name="btnShowDate" id="btnShowDate" value="Show" />

Notice, btnShowDate has an onclick property that’s set to “showCalendar()”. This tells the browser to fire the showCalendar javascript function when the button is clicked.

Now, here’s the javascript code that should go in the head section:

<script type="text/javascript">
    var calendarControl;
    Sys.require(Sys.components.calendar, function () {
        calendarControl = Sys.create.calendar("#travelDate");
    });
    function showCalendar() {
        calendarControl.show();
    }
</script>

The calendarControl variable is declared outside of the Sys.require function scope. This allows us to access it later from showCalendar. As you can see showCalendar is a very simple function and really just a wrapper for calendarControl.show(). There is no reason why you can’t call calenderControl.show() directly in the onclick, but I like to keep things separated this way in case I have to make modifications later or decide to do any other processing before showing the form.

As you can see the calendar is a very powerful client side control. Although the library is still in beta, I’m very excited to learn more about it and create some really awesome javascript pages.

Form defaultbutton attribute in Asp.net mvc

In Asp.net webforms you can add an attribute called “defaultbutton”. This instructs the form as to which button to fire off when the user hits the enter key on the keyboard. This makes a lot of sense, since webforms uses an event driven model. In order to implement this though, a little bit of javascript had to be used. You see the html form tag does not support a default button attribute. So the webforms implementation simply assigns an onkeypress handler to the form and triggers a button click.

Well what about asp.net mvc? Adding a defaultbutton attribute to an asp.net mvc form won’t really do anything. The attribute will render, but the browser won’t know what to do with it and simply ignore it.

So what if you still wanted this behavior? Imagine you have a Submit button and a Clear button on the page and you wanted the submit button to be the default. Currently the form will post if you hit enter, but it won’t send any button values across. We can however come up with a solution using JQuery.

First let’s add the html markup

<%using (Html.BeginForm("DefaultButtonTest", "Home", FormMethod.Post, new { defaultbutton = "SubmitButton",id="MainForm" })){%>
    <%=Html.TextBox("test")%>
    <input type="submit" name="btnSubmit" id="SubmitButton" value="Submit" />
    <input type="submit" name="btnSubmit" id="CancelButton" value="Cancel" />
<%}%>

Notice I used different id’s for the buttons but a single name attribute. This is because in my controller’s action method I only want one input parameter. In the BeginForm helper method I passed in html attribute values, one of which is the default button Id and this is what we will use in javascript.

Note: Make sure you include a reference to the JQuery library. The easiest way to do this is via the CDN. In the head section, add a reference like so:

<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>

Ok now let’s add some code to handle the default button.

<script type="text/javascript">
    var ButtonKeys = { "EnterKey": 13 };
    $(function() {
       $("#MainForm").keypress(function(e) {
       if (e.which == ButtonKeys.EnterKey) {
                var defaultButtonId = $(this).attr("defaultbutton");
                $("#" + defaultButtonId).click();
                return false;
            }
        });
    });
</script>

Here we bind a keypress handler function the the MainForm. In there we check to see which key was pressed (Note I’m using a small javascript object to encapsulate the enter key’s keycode, I think it makes the code more readable.) If the user did press enter we extract the defaultbutton attribute, use a JQuery selector to reference it and call it’s click function.  Pretty straight forward.