Written for Angular 2 (Version 2.0.0-beta7). May work with other versions.
Introduction
Angular 2 moved from dev preview to beta status in December 2015. As it is the possible successor of AngularJS, one of today's most commonly used frameworks for single page web applications, many UI and web developers take a close look at Angular 2's potentials and possibilities in these days.
Many web developers are familiar with today's JavaScript, which usually is ECMAScript version 5. This applies especially to developers, who are familiar with AngularJS, as it is developed and most commonly consumed in this language. Angular 2 on the other hand is written in TypeScript and designed to be consumed in TypScript, Javascript or Dart.
Angular 2 comes with a rich bundle of documentation to get developers started. angular.io provides three sections that are targeted at beginners:
- A 5 minute quick start [^] that covers the minimum basics how to set up file and folder structure, how to implement an (empty) Angular 2 component and how to run it in the browser.
- A five step tutorial [^] which shows the basic mechanics of Angular 2, like controllers, directives, multiple components, dependency injection and routing.
- A developer guide [^] covering these and more topics in deep.
As Angular 2 itself is written in TypeScript, most of the docs and examples are available in TypeScript. But if you start looking for docs in JavaScript or Dart, the options start getting rare. Only the quick start and parts of the developer guide are available for all three languages. This might change when Angular 2 moves from beta to release. But for now JavaScript docs are very rare.
When I worked through this quick start example, the official tutorial was the obvious next step. You can find the official Angular 2 TypeScript Tutorial here: Tutorial: Tour of Heroes - ts [^]
Motivation for this post was to make a JavaScript version of this tutorial available and probably explain a little what was necessary to get it up and running. As TypeScript transpiles to JavaScript, this is possible, but not always completely obvious. We will focus on the TypeScript specific topics that we translated into JavaScript / ES5 and we will mostly skip parts dealing with layout (mostly HTML) or styling (mostly CSS).
As it is always easier to follow an explanation along with working source code, you find my JavaScript example projects for every part along with this article.
TypeScript / JavaScript
Just let me be clear on this. TypeScript definitely has it strengths and potentials and it can be a very good choice to set up a new application, especially if it is based on Angular 2. So this post is not a down vote of TypeScript. This post is intended for developers who are writing AngularJS applications in JavaScript today and want to get to know Angular 2 fast or compare it with AngularJS without struggling with the underlying language.
Enough introduction, let's hit the code...
Using the Code
Part 0 - App with Empty Component
The tutorial starts at the end of the Angular 2 quick start. As this part is available for JavaScript, I suggest, we start there and come back, when the quick start example is running:
https://angular.io/docs/js/latest/quickstart.html
Then we have a component with an empty class, which gets bootstrapped in an Angular 2 application. In the browser, this should look like the screen shot on the right.
Part 1 - Classes and Properties (a.k.a. The Hero Editor)
Part 1 sets up a class with a constructor and two public
properties in TypeScript. One of the properties exposes a custom type Hero
.
Public Properties
First task in this section is to create two public
properties title
and hero
for the class AppComponent
. In TypeScript, it looks like this:
export class AppComponent {
public title = 'Tour of Heroes';
public hero = 'Windstorm';
}
In JavaScript, the direct-forward way to add public
properties to an object is to define and expose them in the constructor function:
constructor: function () {
this.title = 'Tour of Heroes';
this.hero = new Hero(1, 'Windstorm');
}
Interfaces
Next, we change the type of the hero
property from string
to a custom interface. In TypeScript, we first define the type Hero
.
interface Hero {
id: number;
name: string;
}
Then, we can use it in for the property hero
.
public hero: Hero = {
id: 1,
name: 'Windstorm'
};
How does an interface look like in JavaScript? The tutorial says, "Transpiling a class to JavaScript produces code. Transpiling an interface produces — nothing.". And if you look into the transpiled js code, all we find is a plain JavaScript object. The information about a Hero
type or properties id
and name
gets lost during transpilation. So this is what we add to our hero
property:
this.hero = {
id: 1,
name: 'Windstorm'
};
Results
The rest of part 1 covered some HTML layout for this component that we skipped here. The final result should look like the screen shot on the side. Edit the name in the text box and see how the data binding refreshes the (second level) headline.
Part 2 - Lists, DOM-Manipulation and Styling (a.k.a. Master/Detail)
Part 2 of the tutorial covers a lot about DOM manipulation, how to insert or delete elements. For the JavaScript part, we add a new function and access it from the view.
Variables
var HEREOS
is a plain variable. In JavaScript, just remove the type specifier. The tutorial inserts the variable at the bottom of the TypeScript file. If you are working with eslint (or a similar style checker), we would add it at the top of our JavaScript file.
*ngFor
The next paragraph creates a list with repetitive items from the controller. If you are familiar with AngularJS, take a look at how ng-repeat
changed to *ngFor
in Angular 2.
Properties can be added dynamically
The HTML code binds to a variable selectedHero
in the model. In TypeScript, we have to set this explicitly as public
property. In JavaScript, the property selectedHero
will be added to our object, when it is first set by the function onSelect
(next paragraph). As we do not set an initial value, there is no need to define this variable yet.
Prototype functions
The TypeScript onSelect
handler looks like this:
onSelect(hero: Hero) {
this.selectedHero = hero;
}
The easiest implementation in JavaScript would be another public
property in the constructor:
constructor: function () {
this.onSelect = function(hero) {
this.selectedHero = hero;
};
}
If we want to use JavaScript prototypes, we define the function on the prototype
instead. This can be done directly outside of the constructor.
app.AppComponent.prototype.onSelect = function (hero) {
this.selectedHero = hero;
};
Results
Again, there are more tasks in HTML and CSS to do. You can take a close look at ngIf
, another typical Angular feature in Angular 2. After completing part 2, the application should show a styled list and an editor region.
Part 3 - Multiple Components
Until now our (small) application was made of one single block (monolithic). In part 3, we will add basic modularity to our application by adding a second Angular component.
Adding a Second Component
Instead of a hero-detail.ts, we will create an hero-detail.js file. The name of the new component is HeroDetailComponent
. As we already know how to create a component, this part is rather simple. The JavaScript code should look something like this:
app.HeroDetailComponent = ng.core
.Component({
selector: 'my-hero-detail',
})
.Class({
constructor: function () {}
});
Don't forget to load the new JS file in index.html:
<!--
<script src='app/hero-detail.js'></script>
Defining Data-bound Input
We want the hero
property to be updated on Angular's change detection. Therefore, we mark it as input. Analog to the TypeScript code, we register inputs: ['hero']
in the Component
definition of the HeroDetailComponent
.
Defining Directives
TypeScript imports HeroDetailComponent
from ./hero-detail.component';
with the statement import {HeroDetailComponent}
. Therefore, the directive can be referenced as HeroDetailComponent
without further resolving.
import {HeroDetailComponent} from './hero-detail.component';
@Component({
directives: [HeroDetailComponent]
})
As this import
statement is missing in JavaScript, we have to resolve the directive from our Angular app
:
directives: [app.HeroDetailComponent]
Now the application should run again.
Results
In Part 3, we split our AppComponent
and extracted the HeroDetailComponent
. We can find the new file structure in the screen shot to the right. Nevertheless the UI still looks like part 2.
Tools and Resources
There are a few aids that led the way:
Wrap Up
This is the first artilce of this series. We created a small Angular 2 Application with two components yet. In the seccond post we will create a service to simulate communication with a server backend, introduce dependency injection and use a router to navigate between several views.
You can find the second article here: Angular 2 Tutorial in JavaScript/ES5 - Part 4 and 5 [^]
How were your first experiences with Angular 2, especially in combination with JavaScript/ES5? Did you try different appraoches so far? Could you figure out a simpler solution for certain aspects or did I miss something? Please let me know in the comments below.
History
- 28th February, 2016: Initial version of first article (part 1 to 3)
- 5th March, 2016: Reference to second article (part 4 to 5), minor changes
License
The original tutorial, in particular the source code files, are published under an MIT-style license that can be found in the LICENSE file at http://angular.io/license. This tutorial and the source code modifications are published under MIT license, that can be found at https://opensource.org/licenses/MIT.