authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Alexander Mikhalchenko
Verified Expert in Engineering
11 Years of Experience

Alexander is the full-stack developer you bring in to rescue a project with tight schedules. Usually, he prefers less extreme development.

Read More
Share

Angular and Aurelia, descendants of good old JavaScript Angular 1, are fierce competitors, developed and released at approximately the same time and with a similar philosophy, but differing in a number of key ways. In this article, we’ll do side-by-side comparisons of those differences in features and code.

Long story short, Aurelia was created by Rob Eisenberg, known as the creator of Durandal and Caliburn. He worked on the Angular 2 team at Google but left in 2014 when his views on how a modern framework should look differed from theirs.

The similarities persist on a more technical level, too: Templates and the components (or custom elements) associated with them are core to both Angular and Aurelia apps, and both require you to have a root component (i.e. the app). Furthermore, both Angular and Aurelia heavily use decorators for component configuration. Each component has a fixed lifecycle that we can hook into.

So What’s the Difference between Aurelia and Angular 2?

The key difference, according to Rob Eisenberg, is in the code: Aurelia is unobtrusive. When developing an Aurelia app (after configuration), you write in ES6 or TypeScript, and the templates look like absolutely sane HTML, especially when compared to Angular. Aurelia is convention over configuration, and 95% of the time you’ll be just fine using default conventions (such as template naming, element naming, etc.), while Angular requires you to provide configuration for basically everything.

Aurelia is also considered to be more standards compliant, if only because it is not case-sensitive when it comes to HTML tags, whereas Angular 2 is. This means that Angular 2 cannot rely on the browser’s HTML parser, so they created their own.

Another factor to consider when choosing between SPA-frameworks is the community- the ecosystem- around them. Both Angular and Aurelia have all the basics (router, template engine, validation, etc), and it’s easy to get a native modal or use some third-party library, but it comes as no surprise that Angular has a bigger community and bigger development team.

Furthermore, while both frameworks are open source, Angular is mainly developed by Google and is not intended to be commercialized while Durandal, Inc., which employs the core team, is following Ember.js’ model of monetization via consulting and training.

Aurelia vs. Angular: A Code Comparison

Let’s look at some of the most notable features which underline the philosophies behind each framework.

After cloning seed projects for Angular and Aurelia, we have a ES6 Aurelia app (you can use Jspm/System.js, Webpack and RequireJS in combination with ES6 or TypeScript) and a TypeScript Angular app (WebPack), respectively.

Let’s roll.

Data Binding

Before we compare side by side working examples, we have to take a look at some syntactical differences between Aurelia and Angular 2, namely in the key functionality of binding values from the controller to the view. Angular 1 used “dirty checking” for everything, a method which scanned the scope for changes. This, understandably, caused a number of performance issues. Neither Angular 2 nor Aurelia followed that path. Instead, they use event binding.

Data Binding in Angular 2

In Angular, you bind data with square brackets and use parentheses to bind events, like so:



Two-way binding—for when you want changes in application data to reflect on the view and vice versa—is a combination of both square and parenthesis brackets. So, for two-way bound input, this would work just fine:


{{text}}

In other words, parentheses represent an event while square brackets represent a value being pushed to input.

The Angular team did a great job separating binding directions: to the DOM, from the DOM, and bidirectional. There’s also a lot of syntax sugar related to binding classes and styles. Consider, for example, the following snippet as an example of one-way binding:

But what if we want to bind two-way data into a component? Consider the following basic input setup:



{{ text }}



import {Component, Input} from '@angular/core';

@Component(/* ... */)
export class MyComponent {
  @Input() text : string;
}



Text in child: {{ text }}

Note that, to use ngModel, your module must import FormsModule from @angular/forms. Now we have something interesting. Updating the value in the parent input changes values everywhere, but modifying the child’s input only affects that child. If we want it to update the parent value, we need an event informing the parent. The naming convention for this event is property name + 'Change', like so:

import {Component, Input, Output, EventEmitter} from '@angular/core';

@Component(/* ... */)
export class MyComponent {
  @Input() text : string;
  @Output() textChange = new EventEmitter();

  triggerUpdate() {
    this.textChange.emit(this.text);
  }
}

The two-way binding starts working properly right after we bind to the ngModelChange event:



What about one-time binding, when you effectively tell the framework to ignore the bound values even if they change?

In Angular 1, we used {{::value}} to bind one time. In Angular 2, one-time binding gets complicated: the documentation says that you can use the changeDetection: ChangeDetectionStrategy.OnPush attribute in the Component’s configuration, but that will make all your bindings one-time.

Data Binding: The Aurelia Way

In contrast to Angular 2, binding data and events in Aurelia is really simple. You can use either interpolation, just like Angular’s property="${value}", or use one of the following binding types:

property.one-time="value"
property.one-way="value"
property.two-way="value"

The names are self-explanatory. Furthermore, there’s property.bind="value", which is syntax-sugar that self-detects whether the binding should be one-way or two-way. Consider:






In the above snippet, both @bindable and @Input are configurable, so you can easily change things like the name of the property being bound, etc.

What about events? To bind to events in Aurelia, you use .trigger and .delegate. For example, to have a child component fire an event, you might do the following:

// child.js
this.element.dispatchEvent(new CustomEvent('change', {
   detail: someDetails
}));

Then, to listen for that in the parent:




The difference between those two is that .trigger creates an event handler on that particular element whilst .delegate adds a listener on document. This saves resources, but it obviously won’t work for non-bubbling events.

A Basic Example of Aurelia vs. Angular

Now that we’ve covered binding, let’s create a basic component which renders a scalable vector graphic (SVG). It’ll be awesome, therefore we’ll call it awesome-svg. This exercise will illustrate both basic functionality and philosophy for Aurelia and Angular 2. This article’s Aurelia code examples are available on GitHub.

SVG Rectangles Example in Aurelia

Let’s first build out the JavaScript file:

// awesome-svg.js

import {bindable} from 'aurelia-framework';

export class AwesomeSvgCustomElement {
  @bindable title;
  @bindable colors = [];
}

Now for the HTML.

In Aurelia, you can specify the template (or use the inline one) with the annotations @template, @inlineView or even the @noView, but out of the box, it searches for the .html file with the same name as the .js file. The same is true for the custom element’s name—you can set it with @customElement('awesome-svg'), but if you don’t, Aurelia will convert the title to dash-case and look for a match.

Since we didn’t specify otherwise, the element will be called awesome-svg and Aurelia will search for the template with the same name as the js file (i.e. awesome-svg.html) in the same directory:




Notice the