Language Options – An Introduction to Angular2

Before you start developing an Angular2 application, there are a few selections that you have to make. One of those choices is the programming language that you want to use with Angular2. While Angular2 is a JavaScript framework at heart, there are nevertheless, a few options to choose from. In this column, we are going to look at the options and examine the differences in syntax, to help you make that choice.

Background

The JavaScript language specification standard is called ECMAScript, or ES.ECMAScript is standardized by the ECMA International standards organization and overseen by the TC39 committee. ES5 is the version currently supported by most of the browsers. It is the version that many JavaScript developers are still using, especially those developing with plain JavaScript or jQuery. ES6 is the 6th edition of the ECMAScript language specification and was approved in 2015. The specification is named ECMAScript 2015. It is only supported by evergreen browsers today.

Angular2 Language Choices

There are many options available for front-end developers today, and the same applies to Angular2 applications. That’s actually a good thing. The languages that are used the most with Angular2 applications are the following:

Angular2 Language Options

ES5

ES5 is a natural choice for many developers who don’t like to step outside their comfort zone. It is supported by modern and legacy browsers today. Consequently, the initial setup is trivial. You can get started without setting up a development environment with a transpiler, a module loader and possibly a strongly typed language such as TypeScript. Believe it or not, a simple package.json and a boilerplate are all you need:

{
  "name": "ng2-languages-es5",
  "version": "1.0.0",
  "scripts": {
    "start": "npm run lite",
    "lite": "lite-server"
  },
  "license": "ISC",
  "dependencies": {
    "@angular/common":  "2.0.0-rc.1",
    "@angular/compiler":  "2.0.0-rc.1",
    "@angular/core":  "2.0.0-rc.1",
    "@angular/http":  "2.0.0-rc.1",
    "@angular/platform-browser":  "2.0.0-rc.1",
    "@angular/platform-browser-dynamic":  "2.0.0-rc.1",
    "@angular/router":  "2.0.0-rc.1",
    "@angular/router-deprecated":  "2.0.0-rc.1",
    "@angular/upgrade":  "2.0.0-rc.1",

    "core-js": "^2.4.0",
    "reflect-metadata": "0.1.3",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "0.6.12",

    "angular2-in-memory-web-api": "0.0.11",
    "bootstrap": "^3.3.6"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.2.0"
  }
}
<html>
  <head>
    <title>Angular 2 Language Options</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">

    <!-- 1. Load libraries -->
    <!-- IE required polyfill -->
    <script src="node_modules/core-js/client/shim.min.js"></script>

    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>

    <script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
    <script src="node_modules/@angular/core/core.umd.js"></script>
    <script src="node_modules/@angular/common/common.umd.js"></script>
    <script src="node_modules/@angular/compiler/compiler.umd.js"></script>
    <script src="node_modules/@angular/platform-browser/platform-browser.umd.js"></script>
    <script src="node_modules/@angular/platform-browser-dynamic/platform-browser-dynamic.umd.js"></script>

    <!-- 2. Load our 'modules' -->
    <script src='app/data.service.js'></script>
    <script src='app/app.component.js'></script>
    <script src='app/main.js'></script>

  </head>

  <!-- 3. Display the application -->
  <body>
    <my-app>Loading...</my-app>
  </body>

</html>

After a quick “npm install”, we can start creating our first component. It is important to note here, that there have been improvements in ES5 Angular2 syntax. You can read more about it here.

In our app.component.js, we are injecting a DataService that returns an array representing a list of languages.

(function(app) {
  app.AppComponent =
    ng.core.Component({
      selector: 'my-app',
      templateUrl: 'app/app.component.html',
      providers: [DataService]
    })
    .Class({
      constructor: [DataService, function(dataService){
        this.languages = dataService.getLanguages();
      }],
      getTitle: function() {
        return 'Angular 2 Language Options';
      }
    });
})(window.app || (window.app = {}));

In app.component.html (the component’s template), we are looping through the list of languages and displaying it and an unordered list:

<h1>{{getTitle()}}</h1>

<ul *ngFor="#language of languages">
  <li>{{language}}</li>
</ul>

The injected DataService (data.service.js) looks like:

var DataService = function() {};
DataService.prototype.getLanguages = function() {
   return ['ES5','ES6','TypeScript','Dart','Elm','CoffeeScript', 'Etc'];
}

Finally, we need to call Angular2’s bootstrap method in our main.js file, to start the app:

(function(app) {
  document.addEventListener('DOMContentLoaded', function() {
    ng.platformBrowserDynamic.bootstrap(app.AppComponent);
  });
})(window.app || (window.app = {}));

The result is a simple Angular2 application:

ES5 Result

Although the initial setup is fairly simple and the syntax is not so bad, the fifth edition of ECMAScript was standardized in 2009, so it is an old specification. You will also be missing out on many of the productivity features in ES2015 and the great tooling available for TypeScript (and Dart).

ES2015

If you want to write better code and take advantage of the new features in the JavaScript language specification such as Modules, Classes, Arrow Functions, Generators etc. then ES2015 is a great option. It is not currently supported in all browsers today. The code you write in ES2015 needs to be transpiled by a tool and converted to ES5 comparable code, that browsers would understand. Transpilers such as Babel or Traceur can do the job for you. Since we will be using Modules in our Angular2 application, we also need a Module Loader such as SystemJS . That means that the setup is slightly more challenging:

In package.json we need a few more dependencies:

{
  "dependencies": {
    ...
    "systemjs": "0.19.26"
  },
  "devDependencies": {
    "babel-cli": "^6.10.1",
    "babel-plugin-transform-class-properties": "^6.9.1",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-preset-es2015": "^6.9.0",
    "concurrently": "^2.0.0",
    "gulp": "^3.9.1",
    "gulp-babel": "^6.1.2",
    ...
  }

In our index.html, we need to load our scripts using the Module Loader (SystemJS):

    <!-- 2. Configure SystemJS and load our main module -->
    <script src="systemjs.config.js"></script>
    <script>
        System.import ('dist/main.js').catch(function(err) {
            console.error(err);
        });
    </script>

Our app.component.js will be written in a cleaner syntax:

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'my-app',
  templateUrl: 'dist/app.component.html',
  providers: [DataService]
})
export class AppComponent {
  title = 'Angular 2 Language Options';
  constructor(dataService){
    this.languages = dataService.getLanguages();
  }

  static get parameters() {
    return [[DataService]];
  }

}

Note the use of Modules, Decorators and Classes. Our DataService is also injected using the “providers” metadata on the Component.

Our data.service.js will also make use of Decorators to present itself as an Injectable class:

import { Injectable } from '@angular/core'

@Injectable()
export class DataService {
  getLanguages() {
    return ['ES5','ES6','TypeScript','Dart','Elm','CoffeeScript', 'Etc'];
  }
}

And finally our main.js:

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';

bootstrap(AppComponent);

The result is a much cleaner, more understandable and maintainable code.

TypeScript

TypeScript is a superset of JavaScript that has been built by Microsoft and which has been chosen by the Angular2 team for the development of the framework. TypeScript provides many benefits over standard JavaScript by introducing strong typing. Because of this strong typing, TypeScript provides great tooling with syntax checking, inline documentation, code navigation etc. If you want to learn more why the team chose TypeScript, I recommend this post by Victor Savkin, a member of the Angular2 team. TypeScript needs to be compiled to ES5, so we need a Compiler and a Module Loader. We will use a task runner such as Gulp to compile our TypeScript files and SystemJS to load our modules. If you think it’s a hassle to setup that kind of development environment, then you should definitely look at the Angular CLI. You also have Angular Seed which is a great skeleton for Angular2 apps.

Let’s configure TypeScript through tsconfig.json to transpile our code to ES5:

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

Our app.component.ts will look like:

import { Component } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.component.html',
  providers: [DataService]
})
export class AppComponent {
  title:string = 'Angular 2 Language Options';
  languages:string[];
  constructor(private dataService: DataService) {
    this.languages = dataService.getLanguages();
  }
}

Notice the types specified for the title and languages properties and how we are using a private variable to hold the injected service instance.

Our data.service.ts looks fairly similar to ES2015:

import { Injectable } from '@angular/core'

@Injectable()
export class DataService {
  getLanguages(): string[] {
    return ['ES5','ES6','TypeScript','Dart','Elm','CoffeeScript', 'Etc'];
  }
}

Dart

Dart is a non-JavaScript, class based and object oriented language. It offers type checking that is similar to TypeScript, and a great tooling for building large and complex applications. However, since it’s not JavaScript, it’s not the front-end developers favorite language. To get started with Dart, you will need to download the Dart SDK and select an IDE such as WebStorm.  You can read more about it in this guide. If you want to get feel of the syntax, you can take a look at this tutorial on the Angular.io site.

Conclusion

Although Angular2 embraces the latest and greatest technologies in the front-end world, it supports legacy browsers back to IE9, and the ES5 language specification. The development environment setup and the development experience vary based on the language of choice, so it’s up to you to choose whatever makes you more productive.

The completed source code is available on github.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *