ANGULAR 2.0

@tkssharma

github.com/tkssharma

Training

 

Angular js

 

Angular 2

OVERVIEW

ngular 2: ABOUT

  • Mobile first

  • Modular

  • COMplete rewrite

  • Modern browsers

  • WRITTEN in TYPESCRIPT

ngular 2: LANGUAGES

ES5

ES6

TS

DART

ngular 2: TYPESCRIpt 101

  • CLass (declaration)

class Car {

  



  




}
public brand: string;
public number: number;
public isCarNew: boolean;
constructor(brand: string, number: number, isCarNew: boolean){
  this.brand = brand;
  this.number = number;
  this.isCarNew = isCarNew;
}

ngular 2: TYPESCRIpt 101

  • CLass (methods)

class Car {

  



  






}
constructor(public brand: string,
            public number: number,
            public isCarNew: boolean) { }
getCarNumber(): number {
  return this.number;
}

setCarNumber(newNumber: number): void {
  this.number = newNumber;
}

ngular 2: ARCHITECTURE

App component (cmp)

cmp 1

cmp 2

cmp 3

cmp 4

A tree of components

ngular 2: ARCHITECTURE

component

template

DIREctive

property binding

Event binding

injector

Service

app module

my module

Angular 2

components

ngular 2: COMponents

@Component({
  
  

})
export class MyCardComponent {

}
import { Component } from '@angular/core';
selector: 'my-card',
templateUrl: 'my-card.component.html',
styleUrls: ['my-card.component.css']
Component Metadata Properties:

        animations            - list of animations of this component
        changeDetection       - change detection strategy used by this component
        encapsulation         - style encapsulation strategy used by this component
        entryComponents       - list of components that are dynamically inserted into the view 
                                of this component
        exportAs              - name under which the component instance is exported in a template
        host                  - map of class property to host element bindings for events,
                                properties and attributes
        inputs                - list of class property names to data-bind as component inputs
        interpolation         - custom interpolation markers used in this component's template
        moduleId              - ES/CommonJS module id of the file in which this component is defined
        outputs               - list of class property names that expose output events that 
                                others can subscribe to
        providers             - list of providers available to this component and its children
        queries               - configure queries that can be injected into the component
        selector              - css selector that identifies this component in a template
        styleUrls             - list of urls to stylesheets to be applied to this component's view
        styles                - inline-defined styles to be applied to this component's view
        template              - inline-defined template for the view
        templateUrl           - url to an external file containing a template for the view
        viewProviders         - list of providers available to this component and its view children

ngular 2: Templates

  • interpolation 

<p>Hello, my name is {{ user.firstName }}</p>
<p>Hello, my name is {{ getUserFistName() }}</p>

ngular 2: Templates

  • bindings 

// one-way binging (data source => view target)
<user-profile [user]="user"></user-profile>
[target]="expression"
// one-way binging (target => data source)
(target)="statement"
<my-card (click)="select()"></my-card>
// two-way binging (data source <=> view target)
[(target)]="expression"
<input type="text" [(ngModel)]="user.firstName">

ngular 2: BUILD-in dirs

  • ngClass

  • ngStyle

  • ngIf

  • ngFor

  • ngSwitch

ngular 2: ngfor

  • ngFor 

// notice asterisk (*) symbol
<li *ngFor="let user of users">{{user.fullName}}</li>
<user-profile *ngFor="let user of users" [user]="user">
  <user-fullname>{{ user.fullName }}</user-fullname>
</user-profile>

ngular 2: ngclass

  • ngClass

// toggle one class
<div [class.cool]="isCool">This div is cool</div>
setClasses() {
  let classes =  {
    bordered: this.isBordered,
    blue: this.isBlue
  };
  return classes;
}
// toggle multiple classes
<div [ngClass]="setClasses()">
  This div is bordered and blue
</div>

ngular 2: data flow

  • parent => child

application

users

user

user

cards

[users]="appUsers"

[user]="users"

ngular 2: INPUTS

  • @input 

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

@Component({
  moduleId: module.id,
  selector: 'user',
  templateUrl: 'user.component.html',
  styleUrls: ['user.component.css']
})
export class UserComponent {
  
 
}
, Input
// user.component.html
<div class="fullName">{{ user.fullName }}</div>
@Input() user;

ngular 2: data flow

  • CHILD => parent

application

users

user

user

cards

(select)="onSelect()"

(select)="onSelect()"

ngular 2: outputs

  • @output 

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

@Component({
  moduleId: module.id,
  selector: 'user',
  templateUrl: 'user.component.html',
  styleUrls: ['user.component.css']
})
export class UserComponent {
  
 


}
, Output, EventEmitter
// users.component.html
@Output() select = new EventEmitter();

onSelect() { this.select.emit(...); }
<user (select)="onSelected()"></user>

ngular 2: Nested cmps

  • child => parent components

// users.component.html
import { Component } from '@angular/core';


@Component({
  moduleId: module.id,
  selector: 'users',
  templateUrl: 'users.component.html',
  styleUrls: ['users.component.css'],
  
})
export class UsersComponent {

}
import { UserComponent } from './../user.component';
directives: [UserComponent]
<div>
  <user [user]="user"></user>
</div>

deprecated!

ngular 2: CMP lifecycle

  • component lifecycle hooks

  • ngOnInit
  • ngOnChanges
  • ngDoCheck
  • ngOnDestroy

ngular 2: oninit

  • ngOnInit

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

@Component({
  moduleId: module.id,
  selector: 'my-card',
  templateUrl: 'my-card.component.html',
  styleUrls: ['my-card.component.css']
})
export class MyCardComponent                   {

  

}
, OnInit
implements OnInit
ngOnInit() {
  ...
}

Angular 2

ngmodules

ngular 2: ngmodules

app module

http module

forms module

Users module

Auth module

ngular 2: ngmodules

  • @ngModule 

import { NgModule } from '@angular/core';
@NgModule({
  imports:      [ ... ], // other modules
  declarations: [ ... ], // components, directives, pipes
  exports:      [ ... ], // components, directives, pipes
  providers:    [ ... ]  // services
})
export class MyModule { }

ngular 2: App module

  • AppModule 

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './app.component';
@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

ngular 2: Custom module

  • UsersModule 

@NgModule({
  imports:      [ HttpModule, FormsModule, AuthModule ],
  declarations: [ UserComponent, StatusPipe ],
  exports:      [ UserComponent ],
  providers:    [ UserService ]
})
export class UsersModule { }
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';

import { AuthModule } from './../auth/auth.module';
import { UserComponent } from './user.component';
import { UserService } from './user.service';
import { StatusPipe } from './status.pipe';

Angular 2

services & Dependency injection

ngular 2: Services & Di

  • UsersService 

import { IUser } from './../users/user';



export class UsersService {

  
  
  getUsers() {
    ...
  }

  updateUser(user: IUser) {
    ...
  }
}
import { Injectable } from '@angular/core';
@Injectable()
import { AuthService } from './../../auth/auth.service';
constructor(private auth: AuthService) { }

ngular 2: Services & Di

// visible for all components inside this module
import { UserService } from './../users/user.service';

@NgModule({
  imports:      [ ... ],
  declarations: [ ... ],
  exports:      [ ... ],
  providers:    [ UserService ]
})
export class UsersModule { }
// visible only for this component and its children
import { UserService } from './../users/user.service';

@Component({
  selector: 'my-card',
  providers: [ UserService ]
})
export class MyCardComponent { }

ngular 2: Services & Di

  • http service

import { HttpModule } from '@angular/http';
@NgModule({
  imports: [ HttpModule ],
  declarations: [ ... ],
  providers: [ ... ],
  bootstrap: [ ... ]
})
export class AppModule { }

ngular 2: Services & Di

  • UsersService




class UsersService {
  private usersUrl: string = 'api/v1/users';

  constructor(private http: Http) { }

  getUsers() {
    return this.http.get(this.usersUrl)
      .toPromise()
      .then(response => response.json().data)
      .catch(this.handleError);
  }

  private handleError(error: any) { ... }
}
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';

ngular 2: Services & Di

  • UsersService

import { Http          }     from '@angular/http';
import 'rxjs/add/operator/toPromise';

class UsersService {
  private usersUrl: string = 'api/v1/users';

  constructor(private http: Http) {}

  createUsers(user: User) {
    
    return this.http.post(
        this.usersUrl,
        JSON.stringify(user),
        {headers: headers})
      .toPromise()
      .then(response => response.json().data)
      .catch(this.handleError);
  }
}
, Headers
let headers = new Headers({'Content-Type': 'application/json'});

Angular 2

DEMO TIME :)

Angular 2

ROUting

ngular 2: cmp router

<head>
  <base href="/">
  ...
</head>
// set <base href>
// app/app.routing.ts
import { Routes, RouterModule } from '@angular/router';
const appRoutes: Routes = [
  { path: 'users', component: UsersComponent }
];
import { UsersComponent }  from './users.component';
export const routing = RouterModule.forRoot(appRoutes);

ngular 2: cmp router

// app.module.ts
import { NgModule }       from '@angular/core';
import { BrowserModule }  from '@angular/platform-browser';

import { AppComponent }       from './app.component';


import { UsersComponent }    from './users.component';

@NgModule({
  imports: [ BrowserModule           ],
  declarations: [ AppComponent, UsersComponent ],
  providers: [ ... ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
import { routing } from './app.routing';
, routing

ngular 2: cmp router

// navigation
@Component({
  ...
  template: `
    <div class="content">
      


      
    </div>
  `
})
export class AppComponent {}
<router-outlet></router-outlet>
<nav>
  <a routerLink="/users"                          >Users</a>
</nav>
routerLinkActive="active"

ngular 2: cmp router

// users.routing.ts
  • Users feature module

import { Routes, RouterModule } from '@angular/router';

import { UsersComponent }    from './users.component';
import { UserComponent }  from './user.component';
const usersRoutes: Routes = [
  {
    path: 'users',
    component: UsersComponent,
    children: [
      { path: ':id',  component: UserComponent },
    ]
  }
];
export const usersRouting = RouterModule.forChild(usersRoutes);

ngular 2: cmp router

// users.module.ts
  • Users feature module

import { usersRouting } from './users.routing';
@NgModule({
  imports: [ ...,             ],
  declarations: [ ... ],
  providers: [ ... ]
})
export class UsersModule { }
usersRouting

ngular 2: cmp router

  • Users component

import { Component } from '@angular/core';
@Component({
  selector: 'users',
  ...
})
export class UsersComponent {

  

  


}
import { Router } from '@angular/router';
constructor(private router: Router ) { }
viewUser(user: User) {
  this.router.navigate(['/user', user.id]);
}
import { User } from './../user';

ngular 2: cmp router

  • router guards

  • CanActive
  • CanDeactivate
  • Resolve

ngular 2: cmp router

  • CanDeactive guard

import { Component } from '@angular/core';
import { CanDeactivate } from '@angular/router';
@Component({
  selector: 'user',
  ...
})
export class UserComponent                           {


  


}
implements CanDeactivate
canDeactivate() {
  ...
}

ngular 2: cmp router

  • Lazy loading modules

const ROUTES = [
  {
    path: 'users',
    
  },
  {
    path: 'cars',
    
  }
];

@NgModule({
  ...
  bootstrap: [AppComponent],
  imports: [RouterModule.forRoot(ROUTES)]
})
class AppModule {}
loadChildren: 'users.bundle.js',
loadChildren: 'cars.bundle.js',

Angular 2

forms

ngular 2: Forms module

  • Importing forms module 

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './app.component';
@NgModule({
  imports: [ BrowserModule             ],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
import { FormsModule }   from '@angular/forms';
, FormsModule

ngular 2: Forms

  • profile component 

// profile.component.html
<form>
  <div class="form-group">
    <label for="fName">First name</label>
    <input type="text" id="fName" required                             >
  </div>
  <div class="form-group">
    <label for="lName">Last name</label>
    <input type="text" id="lName"                               >
  </div>
  <button type="submit" class="btn btn-default">Save</button>
</form>
@Component({
  selector: 'profile',
  templateUrl: 'profile.component.html',
  ...
})
export class ProfileComponent { }
// profile.component.ts
[(ngModel)]="user.firstName"
[(ngModel)]="user.lastName"

ngular 2: Forms

  • control state classes 

State Class if true Class if false
Control has been visited
 
ng-touched ng-untouched
Control's value has changed
 
ng-dirty ng-pristine
Control's value is valid
 
ng-valid ng-invalid

ngular 2: Forms

  • validation messages 

<form>
  ...
  <div class="form-group">
    <label for="fName">First name</label>
    <input type="text" id="fName" required
       [(ngModel)]="user.firstName"                  >
  </div>
  



</form>
// #fName is a reference to a DOM element within template
#fName="ngModel"
<div [hidden]="fName.valid || fName.pristine" class="alert alert-danger">
  First name is required
</div>

ngular 2: Forms

  • form SUBMIT  

<form                                               >
  <div class="form-group">
    <label for="fName">First name</label>
    <input type="text" id="fName" required
           [(ngModel)]="user.firstName">
  </div>
  ...
  <button type="submit" class="btn btn-default"
                                               >Save</button>
</form>
(ngSubmit)="onSubmit()"
#profileForm="ngForm"
[disabled]="!profileForm.form.valid"
// ngForm directive is added to each form by Angular

Angular 2

Pipes

ngular 2: pipes

  • date pipe 

// 'Aug 23, 2016'
<p>Last login: {{ user.lastLogin | date }}</p>
// 'Aug 23, 2016, 9:45:15 PM'
<p>Last login: {{ user.lastLogin | date:'medium' }}</p>

// '9:45:15 PM'
<p>Last login: {{ user.lastLogin | date:'shortTime' }}</p>

// '45:15'
<p>Last login: {{ user.lastLogin | date:'mmss' }}</p>

ngular 2: Built-in pipes

  • built-in pipes

  • DatePipe
  • UpperCasePipe
  • LowerCasePipe
  • CurrencyPipe
  • PercentPipe

ngular 2: custom pipe

import { Pipe, PipeTransform } from '@angular/core';
  • toSeconds pipe
@Pipe({name: 'ToSeconds' })
export class ToSecondsPipe implements PipeTransform {

  transform(value: number): number {
    // translate milliseconds to seconds
    return Math.round(value / 1000);
  }
}

Angular 2

Angular 1.x and upgrade

ngular 2: Angular 1.5.x

  • module.component 

angular
  .module('myApp')
  .component('userProfile', {
    
    
    



  });
templateUrl: 'userProfile.component.html',
controller: UserProfileController,
class UserProfileController {
  ...
}
bindings: {
  user: '<', // one-way binding (input)
  onSelect: '&' // event callback (output)
}

ngular 2: Cmp lifecycle

  • component lifecycle hooks

  • $onInit()
  • $onChanges
  • $doCheck()
  • $onDestroy()

ngular 2: ui-router 1.0

  • route state

$stateProvider
  .state('root', {
    url: '/users',
    component: 'Users',
    




  });
angular
  .module('myApp')
  .component('users', {
    bindings: {
      users: '<'
    }
  });
// resolved bindings pass automatically
resolve: {
  users: function(UsersService) {
    return UsersService.getUsers();
  }
}

ngular 2: upgrade

a1

a1

a1

a2

a2

a2

ngular 2: upgrade adApter

  • angular 2 cmp => angular 1 

import { UpgradeAdapter } from '@angular/upgrade';
import { UserProfileComponent } from './user-profile.component';
angular
  .module('myApp')
  .directive('userProfile',
    
  );
UpgradeAdapter.downgradeNg2Component(UserProfileComponent));

ngular 2: upgrade adapter

  • angular 1 Cmp => angular 2 

import { UpgradeAdapter } from '@angular/upgrade';
import { Component } from '@angular/core';
const UserAvatar = UpgradeAdapter.upgradeNg1Component('userAvatar');
@Component({
  selector: 'user-profile',
  template: `
    <div>
      <user-avatar></user-avatar>
    </div>
  `,

})
export class UserProfileComponent { }
directives: [UserAvatar]

Angular 2

Conclusion

ngular 2: Final notes

  • angular.io
  • Angular Official Style Guide
  • Angular Cheat Sheet
  • Angular CLI
  • Codelyzer
  • Material2
  • Augury

Thank you!

questions time ;)

Made with Slides.com