I know what you're thinking. Yet another JavaScript framework, don't those come out every two weeks? Yes they do, and I'm sure you've experience some JavaScript framework fatigue. Yet I think it's worth it to look at new frameworks from time to time to see how they work. It can't hurt and you might just learn something.

What is Aurelia?

What is Aurelia? Aurelia is a client side JavaScript framework with an emphasis on simple conventions and ES6/ES7 support. The ES6/ES7 support is transpiled for you so it's compatible with today's browsers. The tag line on the official Aurelia website reads "Aurelia is a next generation JavaScript client framework that leverages simple conventions to empower your creativity."

Rob Eisenberg announced Aurelia earlier this year on his website. Some of the key features are below.

  • ES6/ES7 transpiled support
  • Other than Polyfills no external dependencies
  • Code is highly modularized, only use what you need
  • Adaptive rich two-way binding
  • Simple conventions
  • Advanced client side router via Durandeljs
  • jspm for package management
  • MVVM Architecture
  • Web Components

It's in a very early stage so this might change. In fact it's not ready for production yet according to the author so keep that in mind.

Getting Started

We'll be using some of the concepts from the official Aurelia getting started guide. Feel free to check that guide for more detailed information on any of these topics.

To get started you must have node installed. I recommend using nvm to install everything. All the tools for Aurelia are built on node.

$ npm install -g gulp
$ npm install -g jspm

It's a good idea after installing jspm to add your Github credentials. If not you might get rate limited from github on anonymous requests.

$ jspm endpoint config github //enter in your github credentials

Update for release v0.11.0
At this point you'll need to download the starter skeleton kit. Just grab the latest version, as of this writing it's 0.11.0. In the future they'll be moving to a command line tool to generate a skeleton, unfortunately it's not ready yet.

After downloading the skeleton files you'll need to unzip, and install the jspm dependencies.

$ wget https://github.com/aurelia/skeleton-navigation/archive/0.11.0.tar.gz
$ tar xvfz 0.11.0.tar.gz
$ cd skeleton-navigation-0.11.0
$ npm install
$ jspm install -y

You can take a peek at all the packages by looking at the package.json file. Now we can check if everything is running correctly.

$ gulp watch

There we go! If you open up your web browser and head over to port 9000 on localhost you should see a loading spinner and the navigation page a few seconds later.

Alright, things are working. It's not very exciting. Let's see if we can try out some basic concepts.

The Skeleton Kit

Let's first take a peek at the index.html file.

// index.html
...
  <body aurelia-app>
    <div class="splash">
      <div class="message">Aurelia Navigation Skeleton</div>
      <i class="fa fa-spinner fa-spin"></i>
    </div>

    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
    <script>
      System.import('aurelia-bootstrapper');
    </script>
  </body>

'system.js' is the ES6 system loader while 'config.js' is the configuration for the ES6 loader. The 'aurelia-bootstrapper' is a module that when loaded will look for Aurelia attributes. In this case it will find the aurelia-app in the body tag. This tells Aurelia to load the app.js/app.html file in our src/ directory. Keep that that in mind because you can change it to anything you want.

As noted in the official documentation you are not tied to systemJS nor jspm.

Let's add one more line. We are going to add bootstrap for later.

// index.html
...
   <link rel="stylesheet" type="text/css" href="styles/styles.css">
   <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">

For the purpose of this example we'll delete all the files in the src/ folder.

$ rm src/*
$ cd src

Router

Go ahead and create a brand new app.js file in the src/ folder. The app.js is the view-model. While the app.html is the app view. We'll go over a few concepts.

// app.js

import {Router} from 'aurelia-router';

export class App {
  static inject() { return [Router]; }
  constructor(router) {
    this.router = router;
    this.router.configure(config => {
      config.title = 'Test App';
      config.map([
        { route: ['','start'], moduleId: 'start', nav: true, title:'Starting With Aurelia' }
      ]);
    });
  }
}

In this file we are importing the 'router' from the aurelia-router. Next we are using dependency injection to get that into the application. Your constructor sets the router and we then configure our first route called start. The moduleId is used to tell the application which view/view-model pair to use for that route. In this case it will be start.html/start.js Be aware the files will default to the src/ folder unless you otherwise specify it.

The app.html file is like the main application.hbs file in Ember. It's the default container for everything. This is a suitable place to put in a navigation bar.

// app.html

<template>
  <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">
        <i class="fa fa-home"></i>
        <span>${router.title}</span>
      </a>
    </div>

    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li repeat.for="row of router.navigation" class="${row.isActive ? 'active' : ''}">
          <a href.bind="row.href">${row.title}</a>
        </li>
      </ul>
    </div>
  </nav>

//route will render here
  <div class="page-host">
    <router-view></router-view>
  </div>
</template>

All views must begin with a template tag. A few things to note here is that we have access to the router object. The router object can be used for several things including getting every route that was setup and the href.

For example the router.navigation is an array of all the available routes that were previously setup in the app.js file. We can use href.bind to set the href to the routers href. The repeat.for is a simple repeater. It will create a li tag for every single route in the router.navigation array.

The router-view is similar to the outlet in Ember. It simply is where the route will render.

Data Binding

We now have a basic app.html in it for a route that doesn't exist yet. We'll go ahead and create two new files, start.js and start.html in our src folder.

In the start.js file we'll create a few properties.

// start.js

export class Start{
  constructor(){
    this.heading = 'Testing!!';
    this.firstName = 'Erik';
    this.lastName = 'Hanchett';
  }

  get fullName(){
    return `${this.firstName} ${this.lastName}`;
  }

  start(){
    alert(`Hi, ${this.fullName}!`);
  }
}

The Start class has a constructor with a few properties in it. We also created a simple computed property called fullName. FYI we are using ES6 string interpolation to create it. In addition we created a simple method called start that displays an alert box.

// start.html

<template>
  <section>
    <h2>${heading}</h2>

    <form role="form" submit.delegate="start()">
      <div class="form-group">
        <label for="fn">First Name</label>
        <input type="text" value.bind="firstName" class="form-control" id="fn" placeholder="first name">
      </div>
      <div class="form-group">
        <label for="ln">Last Name</label>
        <input type="text" value.bind="lastName" class="form-control" id="ln" placeholder="last name">
      </div>
      <div class="form-group">
        <label>Full Name</label>
        <p class="help-block">${fullName}</p>
      </div>
      <button type="submit" class="btn btn-default">Submit</button>
    </form>
  </section>
</template>

In the start.html file we have the heading that was retrieved from the start.js property. The value.bind is a one-way binding for everything except form/input controls. When I mention one-way binding what I mean is that changes will flow from our view-model to our view, not from our view to our view-model. Two-way bindings will flow both ways. In addition we have the choice of using value.two-way, or even value.one-time binding if needed.

The last thing we added was a form with a submit.delegate on it. That's an event binding that tells the application to run the start method from our start.js file.

If we fire up gulp watch again, we should now be able to see everything in action on our localhost:9000

Custom Elements

I mentioned earlier that Aurelia has support for Web Components. That's true although you'll need to import all those libraries in to use them. Instead we could use a built in feature for Aurelia called Custom Elements. Custom elements can extend HTML with new tags and they have their own views. If you are into Ember they are similar to components.

In Aurelia there are several behavior types. I won't get into them in this post other then custom elements. All you need to know for now is that there is also attached behaviors and template controllers that are worth looking into.

As an example let's create a Twitter share buttom custom element. If you like to see how I created it using an Ember components check out my Ember Component Examples post.

First things first we need to install the aurelia-templating library using jspm

$ jspm install aurelia-templating -save

We are going to create two files. The twitter-share.html file and the twitter-share.js file. We'll start with the twitter-share-js file.

// twitter-share.js

export class TwitterShare {
  static metadata(){
    return Behavior
      .customElement('twitter-share')
      .withProperty('dsize')
      .withProperty('durl')
      .withProperty('dtext')
      .withProperty('dtags');

  }

}

In this file we are creating a new twitter-share custom element. Since we want to add several attributes to our custom element we add several properties using the withProperty method. We are adding dsize, durl, dtext and dtags.

With most every custom element we have a corresponding html file (there is an option to turn this off .noView(). Here is the html file.

// twitter-share.html

<template>
    <a class='twitter-share-button' data-url=${durl} data-size=${dsize} data-text=${dtext} data-hashtags=${dtags}></a>

	<script>
    	window.twttr=(function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],t=window.twttr||{};if(d.getElementById(id))return;js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);t._e=[];t.ready=function(f){t._e.push(f);};return t;}(document,"script","twitter-wjs"));
	</script>
</template>

As always we must begin with an opening and closing template tag. To show a twitter share button we must create an anchor tag with the data-url data-size data-text and data-hashtags attributes. You can find more information about these in the Twitter documentation..
Since we have access to our class properties we can simply just assign the attributes.

That's about it. Now we can add our custom element to our start route.

// start.html
...
<require from="./twitter-share"></require>
<twitter-share durl.bind="document.url" dsize="Large" dtags="Aurelia" dtext="Aurelia Test!" ></twitter-share>

You'll notice above the dsize, dtags and dtext are bound to string literals. The durl.bind is binding the document.url for the Twitter share button. That being of course the current URL of the webpage.

If all goes well it should look like this.


###Future

This is just a taste of Aurelia. So far it's been easy to setup and use. I'm looking forward to future updates. My next task is to see how well it works with talking to a back-end system.

Have you used Aurelia? Are you interested in the source code for anything I've done in this post? If so check out the source code here.

Subscribe to my email list below and I'll send you a free cheat sheet for Aurelia.

The Best Online Courses on Learning JavaScript

Looking to take your learning a step further with online courses? Are you wanting to jump into Aurelia but not sure if you understand all the JavaScript? I recommend the following courses from Udemy. This is an affiliate link, which means you get help support this blog at the same time!

JavaScript for Beginners - Start to Finish, Quick and Easy

Comprehensive JavaScript Programming

The 4 Major JavaScript Frameworks: From Angular to React

Image Credit to Aurelia

What Is Aurelia? A Getting Started Tutorial