Getting Started With Angular 2.0

Introduction

In this article I am going to create a small app, Address Book, using Angular JS 2.0, which is a jump start for everyone who is going to use Angular JS 2.0 for their future applications. For a demo I have picked a real application, Address Book, where we will perform basic CRUD (Create Read Update Delete) operations. In this demo I will discuss the following important concepts of Angular JS 2.0,

  1. Component Based Architecture.
  2. Overview of AngularJs application architecture.
  3. Creating and using reusable modules knows as Components in Angular 2.0
  4. Bootstrapping application
  5. Routing
  6. Data Binding
  7. Service
  8. Sharing data between components.
  9. Debugging

It’s been a while and there are lots of discussions going on about Angular JS 2.0 since there were major changes done in this version of Angular JS  -- it's even completely rewritten. Angular JS 2.0 follows Component Based Architecture which is slightly different from Angular 1.x which was using MVW architecture to develop applications.

It’s been about a year since Angular JS 2.0 has been announced but there are very few resources available to start with this new framework. This article is for beginners to get familiar with Component Based Architecture with Angular JS 2.0.

What is Component Based Architecture? 

Before jumping forward to the demo application, let’s have a brief understanding of Component Based Design/Architecture.

In component based architecture a component is reusable and extensible which encapsulates its behavior and data, and it also gives an interface to extend its capabilities. We can use a component independently or it can be extended or used with other components. Advantage of component based architecture is it reduces development time as we can reuse existing components and also in order to develop scalable applications we can enhance existing components for better reuse instead of developing new functionality. Here are four simple components which I am using in this AddressBook application.
AddressBook
Since Angular JS 2.0 if all about components, technically in Angular component  there is a JavaScript (ES6) class which is decorated with @Component() and has all the functions in order to add behavior in view (which is also a part of component) and data (to display information in view); the below picture will clear a component architecture in Angular,

architecture

Which will look like,

architecture

Here the information which is shown are properties (data) defined in AddressListComponent, when selecting row we have corresponding functions to handle click event (behavior) in the same component class.

We will discus the rest of the things further; fold your sleeve to jump into code.

Setting up development environment

For this demo I am using WebStorm as IDE but you can use any text editor of your choice. You must have NodeJs installed in your machine as we are going to install all the packages and their dependencies using npm which ships with NodeJs.

Writing your first Angular2 app

If you ar a fan ofa rich editor like Visual Studio, I would encourage you to get yourself familiar with cli (command line interface).

Download the project template from github. Here  the initial folder structure:

structure

Once you are done with the above architecture just copy and paste the code of the corresponding files in your project and ignore node_modules abd typings folder. Now open up command prompt and navigate to your root folder ( if you have WebStorm you would not require command prompt as it has terminal.)

Type npm install wait for awhile and it will create node_module and typings folder for you, then type npm start, if everything has installed correctly you will see,

url
There are some configuration files as follows:

package.json has reference of all dependencies along with npm command shorhands (ex. we used npm start ).

Systemjs.config.js has configuration for systemjs module loader which is being used by angularjs 2.0 for loading modules.

As we are going to use TypeScript for this demo, tsconfig.json has configuration for typescript.

typings.json is configuration for strong typing in typescript.

First Component

In order to create component, let's navigate to app>components folder and open up “app.component.ts”. Here is our AppComponent class,

  1. import { Component }  from '@angular/core';  
  2. import { ROUTER_DIRECTIVES }  from '@angular/router';  
  3. @Component({  
  4.     selector: 'my-app',  
  5.     templateUrl: '../app/components/app.component.html',  
  6.     directives:[ROUTER_DIRECTIVES]  
  7. })  
  8. export class AppComponent {  
  9. }  
This is our first component decorated with @Component along with selector and templateUrl property. You must provide two properties, selector and template, or templateUrl Component decorator. We are importing Component from angular/core module and ROUTER_DIRECTIVES from angular/router module. Component decorator attaches metadata to component and specifies how and what to render in view. We are using ROUTER_DIRECTIVES to enable routing behavior in application.

Before going forward let’s look int the following 3 lines in main.ts,
  1. import { bootstrap } from '@angular/platform-browser-dynamic';  
  2. import { AppComponent } from './components/app.component';  
  3. bootstrap(AppComponent,[]).catch(err => console.error(err));  
If you remember in package.json we have main property with value “main.js” which is javascript version of this typescript(note : typescript files gets transpiled into javascript files . In line 1 we are importing bootstrap module from angular and in line 2 we are importing our component and line 3 is bootstrapping our application using AppComponent (main component). Bootstrap function has 2 parameters, first is main component and second parameter accepts an array of global dependencies.

Now go to Index.html file, we have <my-app>Loading...</my-app> tags to render our component.

So far we have seen how to create a simple component along with html markup.

Implementing Routes

Routing is used to provide navigation in angularjs applications. As we require navigation support in every application, in our demo application we will have 2 pages, details and listing. Let's create a new file app>app.routes.ts as follows :
  1. import { provideRouter, RouterConfig } from '@angular/router';  
  2.   
  3. // export routes  
  4. export const routes: RouterConfig = [  
  5.     { path: '', component: null },  
  6.     { path: 'list', component: null }  
  7. ];  
  8.   
  9. export const APP_ROUTER_PROVIDERS = [  
  10.     provideRouter(routes)  
  11. ];  
where routes contains list for path and its component, since we don't have any relevant component we will use null (which will give an error), in main.ts file update.
  1. import {APP_ROUTER_PROVIDERS} from './app.routes';  
  2. bootstrap(AppComponent,[APP_ROUTER_PROVIDERS]).catch(err => console.error(err));  
In this we are importing route providers from app.routes file and adding in bootstrap.

If you have worked on angular 1.x there was ng-view directive, similarly we have to add route-outlet directive as, <router-outlet></router-outlet> in app.component.html page as follows.
  1. <div class="col-md-12">  
  2.     <nav class="navbar navbar-default">  
  3.         <div class="container-fluid">  
  4.             <div class="navbar-header">  
  5.                 <a class="navbar-brand" [routerLink]="['/list']">Address Book</a>  
  6.             </div>  
  7.             <ul class="nav navbar-nav">  
  8.                 <li>  
  9.                     <a [routerLink]="['/list']">Contact List</a>  
  10.                 </li>  
  11.                 <li>  
  12.                     <a [routerLink]="['/detail']">Details</a>  
  13.                 </li>  
  14.             </ul>  
  15.         </div>  
  16.     </nav>  
  17.   
  18.     <router-outlet></router-outlet>  
  19. </div>  
In order to view results let's add a new component for list and add app> address-list.component.ts and add following:
  1. import { Component } from '@angular/core';  
  2.   
  3. @Component({  
  4.     selector: 'contact-list',  
  5.     templateUrl:'../app/components/address-list.component.html'  
  6. })  
  7. export class AddressListComponent{  
  8.   
  9.     private addresses:Array<any>;  
  10.   
  11.     constructor(){  
  12.         this.addresses = this.getDefault();  
  13.     }  
  14.   
  15.     getDefault(){  
  16.         return  [  
  17.             {id:1,name:"Anupam Singh",profile:"UX Developer", address: "New Delhi 110045",phone:"001 8753-3648-002" ,email:"anupamsingh@abc.com" },  
  18.             {id:2,name:"Mohit",profile:"Software Developer", address: "Dwarka, New Delhi 110045",phone:"001 8753-3648-002" ,email:"mohit@abc.com"},  
  19.             {id:3,name:"Anurag",profile:"Software engineer", address: "Gurgaon, Haryana",phone:"001 8753-3648-002" ,email:"anrag@abc.com"}  
  20.         ];  
  21.     }  
  22.   
  23. onKey(event:any) {  
  24.     if(event.target.value==''){  
  25.         this.addresses = this.getDefault();  
  26.         return;  
  27.     }  
  28.   
  29.     var addresses = [];  
  30.     this.getDefault().forEach(function (item){  
  31.         if(item.name.toLowerCase().indexOf(event.target.value.toLowerCase())>-1) {  
  32.             addresses.push(item);  
  33.         }  
  34.     });  
  35.   
  36.     this.addresses = addresses;  
  37. }  
  38.   
  39. }  
In this component we are using addresses array with default values. Html template for this component is as follows.

app>components >address-list.component.html,
  1. <div contact-list class="box border green">  
  2.     <div class="box-title">  
  3.         <h4><i class="fa fa-book"></i>Address Book</h4>  
  4.         <form class="form-search ng-pristine ng-valid">  
  5.             <input (keyup)="onKey($event)" type="text" class="form-control " placeholder="Search by name">  
  6.         </form>  
  7.     </div>  
  8.     <div class="box-body">  
  9.         <div class="panel-body" style="min-height: 200px; max-height: 300px;overflow-y: scroll;">  
  10.             <div class="row-fluid" >  
  11.                 <div class="span12" *ngFor ="let address of addresses">  
  12.                     <div class="contact well well-small clearfix" style="cursor:pointer;" (click)="onSelect(address)">  
  13.                         <div class="media-body">  
  14.                             <h4 class="media-heading ng-binding">{{address.name}} <small>{{address.profile}}</small></h4>  
  15.                         </div>  
  16.                     </div>  
  17.                 </div>  
  18.             </div>  
  19.         </div>  
  20.     </div>  
  21.   
  22. </div>  
Directive Events and Binding

In address-list.component.html template there is simple angular expressions {{}}, *ngFor directive and events, let' discuss all of them. 
  1. (click) and (keyup) : These are events associated with onclick and onkeyup, in angular2 you can bind common events like this --remember to remove prefix ‘on’. And create function in component class to handle the same.
  2. $event contains metadata of performed event.
  3. *ngFor directive new just like ng-repeat to generate html markup as per collection, but the way we pass parameter(s) is different.

The rest of the things are understood. We will use other directive eg. ngModel, ngIf in this project, but to keep things simple bear with those for now.

Note: In angular2 we use [()] notation for two way binding and [] for one way binding.

Now open up app.routes.ts and update this component as :

{ path: '', component: AddressListComponent },
{ path: 'list', component: AddressListComponent },


Quite simply, here we are using routerLink directive to implement navigation. Now if you will run your application it will look like,

application

As you will type any string it will filter list accordingly. If you will click on Contact list you will get the same view, because we have only one view.

We will go ahead and create a new component address-detail but before going for that, let’s create a Service to remove complexity from the component.

Creating Service (@Injectable)

Now let’s add a new component which will display contact details. Create a new typescript file go to app>services >commonService.ts

  1. import { Injectable } from '@angular/core';  
  2.   
  3. @Injectable()  
  4. export class Common{  
  5.     public contacts= [  
  6.         {id:1,name:"Anupam Singh",profile:"UX Developer", address: "New Delhi 110045",phone:"001 8753-3648-002" ,email:"anupamsingh@abc.com" },  
  7.         {id:2,name:"Mohit",profile:"Software Developer", address: "Dwarka, New Delhi 110045",phone:"001 8753-3648-002" ,email:"mohit@abc.com"},  
  8.         {id:3,name:"Anurag",profile:"Software engineer", address: "Gurgaon, Haryana",phone:"001 8753-3648-002" ,email:"anrag@abc.com"}  
  9.   
  10.     ];  
  11.   
  12.     public getContacts(){          
  13.         return this.contacts;  
  14.     }  
  15.       
  16.     getById(id:number){  
  17.         var selected =  null;  
  18.         this.contacts.forEach(function (contact) {  
  19.             if(contact.id==id){  
  20.                 selected = contact;  
  21.             }  
  22.         });  
  23.   
  24.         return selected;  
  25.     }  
  26.       
  27.     public add(contact):void{  
  28.         this.contacts.push(contact);  
  29.     }  
  30.     public update(contact):void{  
  31.         var ct= this.getById(contact.id);  
  32.         ct.name=contact.name;  
  33.         ct.profile=contact.profile;  
  34.         ct.address=contact.address;  
  35.         ct.email=contact.email;  
  36.     }  
  37.     public get(){  
  38.         return this.contacts;  
  39.     }  
  40.   
  41. }  
What I have done is I have put all contact information in Common class. Note that class is decorated with @Injectable() which mean when we will create component with constructor argument with type Common(above TypeScripe class) and framework will inject instance of Common class into it this is called dependency injection, and it's being handled by framework. We just need to include Injectable from angular/core. Apart from Injectable it’s a simple typescript class, kind of a repository which has in memory CRUD operations.

In order to use this I just need to pass constructor parameter as,
  1. constructor(  
  2. private service: Common  
  3. ){}  
Now I can use everything which is defined in Common class.

Adding Detail View Component

Let's add a new component app>components>address-detail.component.ts,
  1. import { Component,OnInit,OnDestroy } from '@angular/core';  
  2. import { Router , ActivatedRoute } from '@angular/router';  
  3. import {Common} from "../services/commonService";  
  4.   
  5. @Component({  
  6.     selector: 'contact-detail',  
  7.     templateUrl:'../app/components/address-detail.component.html',  
  8.     providers:[Common]  
  9.   
  10. })  
  11. export class AddressDetailComponent implements OnInit, OnDestroy{  
  12.   
  13.     private selectedContact;  
  14.     private sub;  
  15.     constructor(  
  16.         private route: ActivatedRoute,  
  17.         private router :Router,  
  18.         private service:Common  
  19.     ){}  
  20.     ngOnInit() {  
  21.         this.sub = this.route  
  22.             .params  
  23.             .subscribe(params => {  
  24.                 if(params['id']){  
  25.                     this.selectedContact = this.service.getById(parseInt(params['id']));  
  26.                 }  
  27.             });  
  28.     }  
  29.     ngOnDestroy() {  
  30.         if (this.sub) {  
  31.             this.sub.unsubscribe();  
  32.         }  
  33.     }  
  34.     backToList(){  
  35.         this.router.navigate(['/'])  
  36.     }  
  37. }  
In this component we are using Common service which we just created, as you can see constructor arguments. Apart from Service we are using OnInit and OnDestroy interfaces as TypeSctipt support interface just like other strongly typed programming languages (eg. C# , JAVA) and we are also using providers metadata. Let’s discuss above terms in detail. 
  1. Providers
    As I mentioned, angular 2 framework uses dependency injection in order to inject instance of Injectables (Common service in our case), using providers parameter we specify where to look for those dependencies, so in this component we specified inject instance of Common class where constructor has the type of Common. In this component we are also using ActivatedRoute and Router services but not specifying those in providers because those are in-built services.

  2. OnInit and OnDestroy
    These are component life cycle methods since ActivatedRoute uses Observables(see RxJs for more detail) so we are using subscribe and unsubscribe methods here to retrieve values from route. We generally place instantiation of local variable inside OnInit because framework looks for constructor arguments for DI.

  3. We are using router.navigate method to redirect user to another page. Redirect pattern is router.navigate([‘path’,’parameter1’,’parameter2’…]).

    Now we have added a new component, let’s change app.route.ts file and add new route,

    { path: 'detail/:id', component: AddressDetailComponent }

    And add onSelect method in address-list.ts file as follws,
    1. onSelect(address){  
    2. this.router.navigate(['/detail',address.id]) // this how we pass parameter  
    3. }  
    Now if you will browse application and click on any contact it will take you to detail page as follows:

    application

    That’s was great!

    great

So far we have created components, routes and serviceand also looked into a few directives, now we will discuss very important feature of component based architecture and how it’s done in anguar2.

Advantage of component based architecture is extensibility and reusability. Now we will see how we can establish communication between components.

Sharing Data Between Components

components

Create a new component to edit address app>components>edit-address.component.ts,

  1. import { Component,Input } from '@angular/core';  
  2. import { Router } from '@angular/router';  
  3. import {Common} from "../services/commonService";  
  4.   
  5. @Component({  
  6.     selector: 'edit-address',  
  7.     templateUrl:'../app/components/edit-address.component.html',  
  8.     inputs:['id']  
  9. })  
  10. export class EditAddress{  
  11.   
  12.     public id: number;  
  13.     public name: string;  
  14.     public profile:string;  
  15.     public address: string;  
  16.     public email: string;  
  17.   
  18.     public show:boolean=false;  
  19.       
  20.     constructor(  
  21.         private router:Router,  
  22.         private service: Common  
  23.     ){}  
  24.   
  25.     edit(id){  
  26.         if(this.show){this.show=false;}  
  27.         else{   
  28.             var contact= this.service.getById(id);  
  29.             this.id=contact.id;  
  30.             this.name=contact.name;  
  31.             this.profile=contact.profile,  
  32.             this.address=contact.address;  
  33.             this.email=contact.email;  
  34.             this.show=true;   
  35.         }  
  36.     }  
  37.     update(){  
  38.         ifthis.id > 0 && this.name && this.address && this.email) {  
  39.             this.service.update({  
  40.                 id: this.id,  
  41.                 name: this.name,  
  42.                 profile:this.profile,  
  43.                 address: this.address,  
  44.                 email: this.email  
  45.             });              
  46.             this.name='';  
  47.             this.profile='';  
  48.             this.address='';  
  49.             this.email='';  
  50.   
  51.             this.router.navigate(['/']);  
  52.         }  
  53.     }  
  54.   
  55. }  
Notice another property in @Component decorator inputs, this property is used to retrieve parent component data. I am going to place edit-component inside address-detail component. As I have mentioned earlier we just need to place html tags in order to use component, but unlike angular 1.x directives are not global in angular2. Here are the steps you need to follow to add parent component, 
  1. Reference component using import statement as in address-detail.cmponent.ts we need to add following:

    import {EditAddress} from './edit-address.component'

    and in @Component decorator we need to add:

    directives:[EditAddress]

  2. To share data from parent component, we have already added input in edit-address.component.ts.

  3. Add html markup in address-detail.component.html as:

    <edit-address [id]="selectedContact.id"></edit-address>

    Html template of edit-address component is as follows,
    1. <div class="row">  
    2.     <div class="col-md-2">  
    3.         <button class="form-control"  (click)="edit(id)">Edit</button>  
    4.     </div>  
    5. </div>  
    6. <div *ngIf="show==true">  
    7.     <div class="form-group">  
    8.         <label for="name">Name</label>  
    9.         <input type="text" class="form-control" required  
    10.                [(ngModel)]="name" name="name">  
    11.     </div>  
    12.     <div class="form-group">  
    13.         <label for="profile">Profile</label>  
    14.         <input type="text" class="form-control" required  
    15.                [(ngModel)]="profile" name="profile">  
    16.     </div>  
    17.     <div class="form-group">  
    18.         <label for="address">address</label>  
    19.         <input type="text"  class="form-control"  
    20.                [(ngModel)]="address" name="address">  
    21.     </div>  
    22.     <div class="form-group">  
    23.         <label for="email">Email</label>  
    24.         <input type="text"  class="form-control"  
    25.                [(ngModel)]="email" name="email">  
    26.     </div>  
    27.     <div class="row">  
    28.         <div class="col-md-2">  
    29.             <button class="form-control" (click)="update()">Update</button>  
    30.         </div>  
    31.     </div>  
    32. </div>  

In this template I am using *ngIf to hide and show edit component and ngModel to perform binding directive, about the asterisk they say “The asterisk is "syntactic sugar". It simplifies ngIf and ngFor for both the writer and the reader. Under the hood, Angular replaces the asterisk version with a more verbose <template> form.”

Now it’s time to test all changes, run your project click on any name, you will see detail page as follows:

project

Note: you will not see updated detail in list view since we are using Common service in detail view component. So please download full demo from github from download links.

Just like edit component I have added add component in list view, which I am not going show here to repeat code. If you have followed me till here I am sure you have got a better understanding of framework, but there are lot more things available there so keep your eyes on angular.io.

Now it’s your turn, download the demo project from git hub and play with it.

Wait………..

Do you know DEBUGGING…………………..

Debugging your angular2 app

Since we are using TypeScript which gets compiled into javascript, so the developer tool inthe browser is your friend here, read error messages carefully and then start troubleshooting … and keep your developer console always open. And most importantly remember the debugger keyword.

Leaving you with a typical error message when you forgot to reference service,

service

Project Links:

Conclusion

In this article, I discussed the basics of angular2.0. It’s always good to start with some code and if it is a project then we grab experience to develop real apps with relevant technology, this is the reason I choose AddressBook, a simple project. Since there is a lot of code and you might be stuck somewhere in between try to compare your code with the complete project source code. Or leave comments. Hope you have got a better understanding of this new bird known as Angular 2 .0.