Share via



September 2015

Volume 30 Number 9

Data Points - Revisiting JavaScript Data Binding -- Now with Aurelia

By Julie Lerman

Julie LermanI’ve never been much of a front-end developer, but every once in a while I have a reason to play with a UI. In my June 2012 column, after seeing a user group presentation on Knockout.js, I dug in and wrote an article about data binding OData in a Web site using Knockout (msdn.microsoft.com/magazine/jj133816). A few months later, I wrote about adding Breeze.js into the mix to make the data binding with Knockout.js even easier (msdn.microsoft.com/magazine/jj863129). When I wrote about modernizing an old ASP.NET 2.0 Web Forms app and using Knockout again in 2014, I got teased by some friends who said that Knockout was “so 2012.” Newer frameworks such as Angular also did data binding and so much more. But I wasn’t really interested in the “so much more,” so Knockout was fine for me.

Well, now it’s 2015 and while Knockout is still valid and relevant and awesome for JavaScript data binding, I wanted to spend some time with one of the new frameworks and chose Aurelia (Aurelia.io) because I know so many Web developers who are excited about it. Aurelia was started by Rob Eisenberg, who was behind Durandal, another JavaScript client framework, though he stopped production on that to go work on the Angular team at Google. Eventually he left Angular and, rather than reviving Durandal, created Aurelia from the ground up. There are a lot of interesting things about Aurelia. I have a lot more to learn for sure, but want to share with you some of the data-binding tricks I learned, as well as a bit of trickery with EcmaScript 6 (ES6), the latest version of JavaScript, which became a standard in June 2015.

An ASP.NET Web API to Serve Data to My Web Site

I’m using an ASP.NET Web API I built to expose data I’m persisting with Entity Framework 6. The Web API has a handful of simple methods to be called via HTTP.

The Get method, shown in Figure 1, takes in some query and paging parameters and passes them on to a repository method that retrieves a list of Ninja objects and their related Clan objects using an Entity Framework DbContext. Once the Get method has the results in hand, it transforms those results into a set of ViewListNinja Data Transfer Objects (DTOs), defined elsewhere. This is an important step because of the way JSON is serialized, which is a bit overzealous with circular references from the Clan back to other Ninjas. With the DTOs, I avoid a wasteful amount of data going over the wire and I get to shape the results to more closely match what’s on the client.

Figure 1 The Get Method from the Web API

public IEnumerable<ViewListNinja> Get(string query = "",
  int page = 0, int pageSize = 20)
  {
    var ninjas = _repo.GetQueryableNinjasWithClan(query, page, pageSize);
    return ninjas.Select(n => new ViewListNinja
                              {
                                ClanName = n.Clan.ClanName,
                                DateOfBirth = n.DateOfBirth,
                                Id = n.Id,
                                Name = n.Name,
                                ServedInOniwaban = n.ServedInOniwaban
                              });
    }

Figure 2 shows a view of the JSON results from that method based on a query that retrieved two Ninja objects.

JSON Results from Web API Request for List of Ninjas
Figure 2 JSON Results from Web API Request for List of Ninjas

Querying the Web API Using the Aurelia Framework

The Aurelia paradigm pairs one view model (a JavaScript class) with one view (an HTML file) and performs data binding between the two. Therefore, I have a ninjas.js file and a ninjas.html file. The Ninjas view model is defined as having an array of Ninjas, as well as a Ninja object:

export class Ninja {
  searchEntry = '';
  ninjas = [];
  ninjaId = '';
  ninja = '';
  currentPage = 1;
  textShowAll = 'Show All';
  constructor(http) {
    this.http = http;
  }

The most critical method in ninjas.js is retrieveNinjas, which calls the Web API:

retrieveNinjas() {
  return this.http.createRequest(
    "/ninjas/?page=" + this.currentPage +
    "&pageSize=100&query=" + this.searchEntry)
    .asGet().send().then(response => {
      this.ninjas = response.content;
    });
  }

Elsewhere in the Web app I’ve set up the base URL that Aurelia will find and incorporate it into the request’s URL:

x.withBaseUrl('https://localhost:46534/api');

It’s worth noting that the ninjas.js file is just JavaScript. If you’ve used Knockout, you might recall that you have to set up the view model using Knockout notation so that when the object is bound to the markup, Knockout will know what to do with it. That’s not the case for Aurelia.

The response now includes the list of Ninjas and I set that to the ninjas array of my view model, which gets returned to the ninjas.html page that triggered the request. There’s nothing in the markup that identifies the model—that’s taken care of because the model is paired with the HTML. In fact, most of the page is standard HTML and some JavaScript, with just a few special commands that Aurelia will find and handle.

Data Binding, String Interpolation and Formatting

The most interesting part of ninjas.html is the div, which is used to display the list of ninjas:

<div class="row">
  <div  repeat.for="ninja of ninjas">
    <a href="#/ninjas/${ninja.Id}" class="btn btn-default btn-sm" >
      <span class="glyphicon glyphicon-pencil" />  </a>
    <a click.delegate="$parent.deleteView(ninja)" class="btn btn-default btn-sm">
      <span class="glyphicon glyphicon-trash" />  </a>
    ${ninja.Name}  ${ninja.ServedInOniwaban ? '[Oniwaban]':''}
    Birthdate:${ninja.DateOfBirth | dateFormat}
  </div>
</div>

The first Aurelia-specific markup in that code is repeat.for “ninja of ninjas,” which follows an ES6 paradigm for looping. Because Aurelia comprehends the view model, it understands that “ninjas” is the property defined as an array. The variable “ninja” can be any name, for example “foo.” It just represents each item in the ninjas array. Now it’s just a matter of iterating through the items in the ninjas array. Skip down to the markup where the properties are displayed, for example “${ninja.Name}.” This is an ES6 feature that Aurelia takes advantage of, which is called string interpolation. String interpolation makes it easier to compose strings with variables embedded in them rather than, for example, by concatenating. So with a variable name=“Julie,” I can write in JavaScript:

`Hi, ${name}!`

and it will be processed as “Hi, Julie!” Aurelia takes advantage of ES6 string interpolation and infers one-way data binding when it encounters that syntax. So that last line of code, beginning with ${ninja.Name} will output the ninja properties along with the rest of the HTML text. If you code in C# or Visual Basic, it’s worth noting that string interpolation is a new feature of both C# 6.0 and Visual Basic 14.

I did have to learn a bit more JavaScript syntax along the way, for example the conditional evaluation of the ServedInOniwaban Boolean, which turns out to have the same syntax as C#—condition? true : false. 

The date formatting I’ve applied to the DateOfBirth property is another Aurelia feature and may be familiar to you if you’ve used XAML. Aurelia uses value converters. I like to use the moment JavaScript library to help with date and time formatting and am taking advantage of that in the date-format.js class:

import moment from 'moment';
export class dateFormatValueConverter {
  toView(value) {
  return moment(value).format('M/D/YYYY');
  }
}

Keep in mind that you do need “ValueConverter” in the class name.

At the top of the HTML page, just under the initial <template> element, I have a reference to that file:

<template>
  <require from="./date-format"></require>

Now the string interpolation is able to find the dateFormat­[ValueConverter] in my markup and apply it to the output, as shown in Figure 3.

Displaying All Ninjas with Properties Bound One Way by Aurelia via String Interpolation
Figure 3 Displaying All Ninjas with Properties Bound One Way by Aurelia via String Interpolation

I want to point out another instance of binding in the div, but it’s event binding, not data binding. Notice that in the first hyperlink tag I use a common syntax, embedding a URL in the href attribute. In the second, however, I don’t use href. Instead, I use click.delegate. Delegate is not a new command, but Aurelia does handle it in a special way that’s much more powerful than a standard onclick event handler. Read more at bit.ly/1Jvj38Z. I’ll continue to focus on the data-related binding here. 

The edit icons lead to a URL that includes the ninja’s ID. I’ve instructed the Aurelia routing mechanism to route to a page called Edit.html. This is tied to a view model that’s in a class named Edit.js.

The most critical methods of Edit.js are for retrieving and saving the selected ninja. Let’s start with retrieveNinja:

retrieveNinja(id) {
  return this.http.createRequest("/ninjas/" + id)
    .asGet().send().then(response => {
      this.ninja = response.content;
    });
  }

This builds a similar request to my Web API as before, but this time appending the id to the request.

In the ninjas.js class I bound the results to a ninjas array property of my view model. Here I’m setting the results, a single object, to the ninja property of the current view model.

Here is the Web API method that will get called because of the id that’s appended to the URI:

public Ninja Get(int id)
  {
    return _repo.GetNinjaWithEquipmentAndClan(id);
  }

The results from this method are much richer than those returned for the ninja list. Figure 4 shows the JSON returned from one of the requests.

JSON Results of a WebAPI Request for a Single Ninja
Figure 4 JSON Results of a WebAPI Request for a Single Ninja

Once I’ve pushed the results into my view model, I can bind the properties of the ninja to elements in the HTML page. This time I use the .bind command. Aurelia infers if something should be bound one-way or two-way or some other way. In fact, as you saw in ninjas.html, it used its underlying binding workflow when presented with the string interpolation. There it used one-time, one-way binding. Here, because I’m using the .bind command and am binding to input elements, Aurelia infers that I want two-way binding. That’s its default choice, which I could override by using .one-way or another command in place of .bind.

For brevity, I’ll extract just the relevant markup rather than the surrounding elements.

Here’s an input element bound to the Name property of the ninja property in the model I passed back from the modelview class:

<input value.bind="ninja.Name" />

And here’s another, this time bound to the DateOfBirth field. I love that I could easily reuse the date-format value converter even in this context, using the syntax I learned earlier:

<input  value.bind="ninja.DateOfBirth | dateFormat"  />

I also want to list the equipment on the same page, similar to how I listed the ninjas so they can be edited and deleted. For demonstration, I’ve gone as far as displaying that list as strings, but haven’t implemented the edit and delete features, nor a way to add equipment:

<div repeat.for="equip of ninja.EquipmentOwned">
  ${equip.Name} ${equip.Type}
</div>

Figure 5 shows the form with the data binding.

The Edit Page Displaying the Equipment List
Figure 5 The Edit Page Displaying the Equipment List

Aurelia also has a feature called adaptive binding, which allows it to adapt its binding capabilities based on available features of the browser or even the objects that are passed in. It’s pretty cool and designed to be able to work alongside browsers and libraries as they evolve over time. You can read more about the adaptive binding at bit.ly/1GhDCDB.

Currently, you can only edit the ninja name, birth date and Oniwaban indicator. When a user unchecks Served in Oniwaban and hits the Save button, this action calls into my view model save method, which does something interesting before pushing the data back to my Web API. Currently, as you saw in Figure 4, the ninja object is a deep graph. I don’t need to send all of that back for saving, just the relevant properties. Because I’m using EF on the other end, I want to be sure the properties I didn’t edit also go back so they don’t get replaced with null values in the database. So I’m creating an on-the-fly DTO called ninjaRoot. I’ve already declared ninjaRoot as a property of my view model. But the definition of ninjaRoot will be indicated by how I build it in my Save method (see Figure 6). I’ve been careful to use the same property names and casing that my WebAPI expects so it can deserialize this into the known Ninja type in the API.

Figure 6 The Save Method in the Edit Model-View

save() {
        this.ninjaRoot = {
          Id: this.ninja.Id,
          ServedInOniwaban: this.ninja.ServedInOniwaban,
          ClanId: this.ninja.ClanId,
          Name: this.ninja.Name,
          DateOfBirth: this.ninja.DateOfBirth,
          DateCreated: this.ninja.DateCreated,
          DateModified: this.ninja.DateModified
        };
        this.http.createRequest("/ninjas/")
          .asPost()
          .withHeader('Content-Type', 'application/json; charset=utf-8')
          .withContent(this.ninjaRoot).send()
          .then(response => {
            this.myRouter.navigate('ninjas');
          }).catch(err => {
            console.log(err);
          });
    }

Notice the “asPost” method in this call. This ensures the request goes to the Post method in my Web API:

public void Post([FromBody] object ninja)
{
  var asNinja =
    JsonConvert.DeserializeObject<Ninja>
    (ninja.ToString());
  _repo.SaveUpdatedNinja(asNinja);
}

The JSON object is deserialized into a local Ninja object and then passed on to my repository method, which knows to update this object in the database.

When I return to the Ninjas list on my Web site, the change is reflected in the output.

More Than Just Data Binding

Keep in mind that Aurelia is a much richer framework than for just data binding, but true to my nature, I focused on data in my first steps to explore this tool. You can learn so much more at the Aurelia Web site, and there’s a thriving community at gitter.im/Aurelia/Discuss.

I want to proffer a nod of thanks to the tutaurelia.net Web site, a blog series about combining ASP.NET Web API and Aurelia. I leaned on author Bart Van Hoey’s Part 6 for my first pass at displaying the list of ninjas. Perhaps by the time this article is published, there will be more posts added to the series.

The download for this article will include both the Web API solution and the Aurelia Web site. You can use the Web API solution in Visual Studio. I’ve built it in Visual Studio 2015 using Entity Framework 6 and the Microsoft .NET Framework 4.6. If you want to run the Web site, you’ll need to visit the Aurelia.io site to learn how to install Aurelia and run the Web site. You can also see me demonstrate this application in my Pluralsight course, “Getting Started with Entity Framework 6,” at bit.ly/PS-EF6Start.


Julie Lerman is a Microsoft MVP, .NET mentor and consultant who lives in the hills of Vermont. You can find her presenting on data access and other .NET topics at user groups and conferences around the world. She blogs at thedatafarm.com/blog and is the author of “Programming Entity Framework” (2010), as well as a Code First edition (2011) and a DbContext edition (2012), all from O’Reilly Media. Follow her on Twitter at twitter.com/julielerman and see her Pluralsight courses at juliel.me/PS-Videos.


Thanks to the following technical expert for reviewing this article: Rob Eisenberg (Durandal Inc.)
Rob Eisenberg has a decade of experience focusing on user interface architecture and engineering. He's the creator of multiple UI frameworks such as Caliburn.Micro and Durandal, which have been used by thousands of developers worldwide. A former Angular 2.0 team member, Rob currently leads the Aurelia project, a next generation JavaScript client framework for mobile, desktop and Web that leverages simple conventions to empower your creativity. Learn more at https://aurelia.io/