Angular from 1.x to 2

angular-banner.jpg

Let’s try to imagine a prospect. You, working as a front-end developer, find building web applications with the stable and perfomant AngularJS 1.x framework quite comfortable. But then suddenly on a beautiful day, Google announces the Angular 2 – the “rewritten and including breaking changes” version. Question: stay or go?

Actually, you do not have to imagine as it has already come into reality. When I tried studying Angular 2 the first time, it was confusing and frustrating as things looked completely different than that I was used to. Felt completely lost... But several weeks ago, I re-checked the guide about Angular 2 and to be honest, it has evolved to the very point that I was immediately struck with a strong impression.

In this article, I will introduce some key points when changing from Angular 1.x to Angular 2. You can still find a lot of them in the reference links at the bottom of the article.

-----TypeScript-----

This might be the first thing you want to have a look as Angular 2 is written in TypeScript.

If you haven’t heard about it yet, TypeScript is a typed superset of Javascript that compiles to plain JavaScript. Compared with Javascript, TypeScript has the advantage not only in providing optional static typing, classes, interfaces, vice versa but also enable our IDEs to provide a richer environment for spotting errors as you type the code.

Here is a file written in TypeScript named greeting.ts,

class Greeter {
  constructor(public greeting: string) { }
  greet() {
      return "<h1>" + this.greeting + "</h1>";
  }
};

var greeter = new Greeter("Hello, world!");

document.body.innerHTML = greeter.greet();

which is compiled into greetingt.js in Javascript:

var Greeter = (function () {
  function Greeter(greeting) {
      this.greeting = greeting;
  }
  Greeter.prototype.greet = function () {
    return "<h1>" + this.greeting + "</h1>";
  };
  return Greeter;
}());
;
var greeter = new Greeter("Hello, world!");
document.body.innerHTML = greeter.greet();

-----Good bye ng-app, say hello to Bootstrapping-----

The term Bootstrapping is equivalent of the initialization or starting of your Angular app. In Angular 1.x, there are two ways to do this: Automatically bootstrapping by using ng-app directive

<div ng-app="myAngularApp">...</div>

or bootstrap from the Javascript

angular.module('myAngularApp', []);
angular.bootstrap(document, ['myAngularApp']);

In AngularJs 2, this technique remains the same, however, there is a bit difference in the way of implementation. The bootstrap method needs importing from @angular/platform-browser-dynamic so that it can be used.

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

-----Component and the death of $scope-----

Here is the part that might get on the nerves of Angular 1 developers at first. We have a totally new comer: Component. What is a component and why is it here?

Angular 2 is entirely component-based programming - a concept that might sound familiar to ReactJs developers. Let's take a look at the user.component.ts below:

//user-detail.component.ts
import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'user-detail',
  templateUrl: 'user-detail.component.html'
})

export class UserDetailComponent {
  name: string;
  age: number;
  hobbies: string[];

  constructor() {
    this.name = '不倶戴天';
    this.age = 22;
    this.hobbies = = ["Reading", "Games", "Sleeping"];
  }

  introduceName(): void {
    console.log('私は' + this.name + 'と申します。');
  }
}

This creates a component called UserComponent, which will be identified in markup as

<div>
  <user-detail></user-detail>
</div>

So components are simply directives that are always associated with a direct template (in the case above, user-detail.component.html). Basically, a component is like the combination of directive and controller of Angular 1:

  • The name of the directive is specified in attribute selector
  • The template associated is specified in atribute templateUrl
  • The member data & methods go inside the component's class.

main-qimg-d84ff3356ace830dab3009cf3430afa8.png

Remember that "in Angular 2, everything is component". The birth of Component has also declared the execution of controller and $scope object.

-----Data binding and ngModel-----

In Angular 2, the denotation of two-way binding is [()], referred as as "a banana in the box". This syntax is a shortcut for defining both property binding (from the component to view and event binding (from the view to component), thus providing two-way binding.

two-way-data-binding-box-of-bananas-in-angular2.png

<!--user-list.component.html -->
<input type="text" [(ngModel)]="name" />
<p>My name is {{name}}</p>

As you type the name in the input field, the name displayed also changes.

-----Data iteration-----

Yeah yeah, I know I know. The ng-repeat-thing, right? Well, that, we can also say kiss goodbye. The directive is now called ngFor and its syntax is changed as below:

//user-list.component.ts
import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'user-list,
  templateUrl: 'user-list.component.html'
})
export interface User {
name: string;
age: number;
hobbies: string[];
}
export class UserListComponent {
userList: User[] = [{
  name: 'Josh',
  age: 22
}, {
  name: 'Jenna',
  age: 26
}, {
  name: 'Jim',
  age:29}];
}
<!--user-list.component.html-->
<ul class="list-user">
  <li *ngFor="let user of userList">{{user.name}}, {{user.age}}</li>
</ul>

Something strange with the asterisk. Just ngFor is already enough, why bother adding that mark? ngFor, ngIf and ngSwitch are structural directives which change the DOM layout by adding and removing DOM elements. In Angular 2, structural directives can only be applied to a <template> so giving it an asterisk is considered the short form that can be applied to any element. The <template> element is created implicitly behind the scene.

  <li template ="ngFor let user of userList">{{user.name}}, {{user.age}}</li>

-----Pipe-----

If you have become familiar with Angular 1’s filter, this won’t cause you trouble. Angular 1 filters are quite helpful for formatting output in templates. With Angular 2, this awesome feature is now called Pipe. Below is the table of comparison between Filter and Pipe.

Capture.PNG

We can also create our custom Pipe if the default pipes do not satisfy our needs. Below is a custom pipe for filtering a list of users by name:

//user-name.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { User } from '../models/user;

@Pipe({
  name: 'userName'
})

export class UserNamePipe implements PipeTransform {
  transform(userList: User[], query: string) {
    if (!userList) {
      return [];
    }
    return userList.filter(user => {
      return user.name.toLowerCase().includes(query.toLowerCase());
    });
  }
}
<!--user-list.component.html-->
<p>
  Search:
  <input [(ngModel)]="query" />
</p>
<ul class="list-user">
  <li *ngFor="let user of userList | userName">{{user.name}}, {{user.age}}</li>
</ul>

References links:

Angular 1.x to 2 Guide

Angular Upgrade Guide