angular2 and typescript

73
Building Powerful Enterprise Apps with Angular 2 and TypeScript

Upload: david-giard

Post on 13-Jan-2017

481 views

Category:

Technology


2 download

TRANSCRIPT

Building Powerful Enterprise Apps

with Angular 2 and TypeScript

Microsoft Technical Evangelistblog: DavidGiard.comtv: TechnologyAndFriends.comtwitter: @DavidGiardEmail: [email protected]

David Giard

Single Page Applications

@DavidGiard

Traditional Web App

HTML Page

Click me!

Server

Request

Response

Thank you, David!

@DavidGiard

Single Page App

HTML Page

Click me!

Server

Request

Response

Thank you, David!

{‘name’: ‘David’}

@DavidGiard

Angular• SPA Framework• Open Source• Data Binding• Components• Modularize

@DavidGiard

TypeScript• Open Source• Superset of JavaScript• Transpiles to JavaScript

@DavidGiard

TypeScriptfoo.ts foo.js

Transpile

foo.map

@DavidGiard

Transpile

@DavidGiard

TypeScript Transpiling• Command Line: tsc or tsc -w• Grunt, Gulp, Webpack, etc.• Visual Studio

@DavidGiard

TypeScript Advantages• Productivity• Static Type Analysis• Language Tool Support• Better management of large codebases

@DavidGiard

Type Checkingvar num1 = 5;var num2 = 10;…

num2=“10”;…

var sum = num1 + num2;

@DavidGiard

Type Checkingvar num1: number = 5;var num2 : number = 10;…

num2=“10”;…

var sum: number = num1 + num2;

@DavidGiard

tsconfig.json{ "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" ]}

@DavidGiard

Angular 2

@DavidGiard

Key Parts of Angular• Modules• Components• Templates• Directives• Services• Routing

@DavidGiard

Modules

@DavidGiard

Modules• Built into Angular 2• Makes it easier to split code into smaller pieces• Import one module into another• Export module to make it available for import

@DavidGiard

Modulesimport {Component} from 'angular2/core';@Component({ selector: 'my-selector', template: '<h1>Hello World</h1>'})export class DemoComponent { }

Available outside this

module

Use exported module

In this module

@DavidGiard

Components

@DavidGiard

Components• Class (properties & methods)• Decorated with @Component• Template• Selector• Imported references

@DavidGiard

Templates and Selectors

@DavidGiard

Templates and Selectorsimport {Component} from 'angular2/core';

@Component({ selector: 'my-selector', template: '<h1>Hello World</h1>'})export class DemoComponent { }

@DavidGiard

Selector@Component({ selector: 'my-selector', template: '<h1>Hello World</h1>'})export class DemoComponent { }

<my-selector>Loading...</my-selector>

@DavidGiard

<my-selector>Loading...</my-selector>

Templates@Component({ selector: 'my-selector', template: '<h1>Hello World</h1>'})export class DemoComponent { }

Output

Loading…

@DavidGiard

<my-selector>Loading...</my-selector>

Templates@Component({ selector: 'my-selector', template: '<h1>Hello World</h1>'})export class DemoComponent { }

Output

Hello World

@DavidGiard

<my-selector>Loading...</my-selector>

Templates: Multi-Line

Output

Hello WorldWelcome

@Component({ selector: 'my-selector', template: `

<h1>Hello World</h1><div>Welcome!</div>`

})export class DemoComponent { }

@DavidGiard

<my-selector>Loading...</my-selector>

Templates: External file@Component({ selector: 'my-selector', templateUrl: 'myPage.html'})export class DemoComponent { }

Output

<h1>Hello World</h1><div>

Welcome!</div>

myPage.html

Hello WorldWelcome

@DavidGiard

<my-selector>Loading...</my-selector>

Components: Properties

Output

<h1>Hello World</h1><div>

Welcome {{customerName}}!</div>

myPage.html

Hello WorldWelcome David

@Component({ selector: 'my-selector', templateUrl: 'myPage.html'})export class DemoComponent {

customerName:string = “David”;}

@DavidGiard

Data Binding• Interpolation• One-Way Property Binding• 2-Way Property Binding• Event Binding

@DavidGiard

Interpolation• Double curly braces around data• e.g.,

{{customerName}}

@DavidGiard

Interpolation@Component({ selector: 'my-selector', template: '<h1>Hello World</h1>'})export class DemoComponent {

id=1;customerFirstName='David';customerLastName='Giard';

}

@DavidGiard

Interpolation@Component({ selector: 'my-selector', template: '<h1>Hello {{customerFirstName}}</h1>'})export class DemoComponent {

id=1;customerFirstName='David';customerLastName='Giard';

}

1-Way Data Binding

Hello David

@DavidGiard

Interpolation@Component({ selector: 'my-selector', template: '<h1>Hello {{customer.FirstName}}</h1>'})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}

}export class Customer{

FirstName: string;LastName: string;

}

@DavidGiard

Interpolation@Component({ selector: 'my-selector', template: `<h1>{{customer.FirstName}} Details</h1><div>First: {{customer.FirstName}}</div><div>Last: {{customer.LastName}}`})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}

}David DetailsFirst: DavidLast: Giard

@DavidGiard

1-Way Data Binding• Square brackets around property• []

@DavidGiard

1-Way Data Binding@Component({ selector: 'my-selector', template: ‘<button [disabled]="dataNotChanged">Save</button>’})export class DemoComponent {

dataNotChanged= true;}

Save

@DavidGiard

1-Way Data Binding@Component({ selector: 'my-selector', template: ‘<button [disabled]=" dataNotChanged">Save</button>’})export class DemoComponent {

dataNotChanged = true;}

Save

@DavidGiard

1-Way Data Binding@Component({ selector: 'my-selector', template: ‘<button [disabled]=" dataNotChanged">Save</button>’})export class DemoComponent {

dataNotChanged = false;}

Save

@DavidGiard

2-Way Data Binding• Requires FormsModule• [(property_to_bind)]

@DavidGiard

2-Way Data Binding@Component({ selector: 'my-selector', template: `<h1>{{customer.FirstName}} Details</h1><div>First: <input [(ngModel)]="customer.FirstName" </div><div>Last: <input [(ngModel)]="customer.LastName" </div>`})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}

}

2-way data binding

David DetailsDavid

Giard

First:

Last:

1-way data binding

@DavidGiard

2-Way Data Binding@Component({ selector: 'my-selector', template: `<h1>{{customer.FirstName}} Details</h1><div>First: <input [(ngModel)]="customer.LastName" </div><div>Last: <input [(ngModel)]="customer.FirstName" </div>`})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}

}D Details

D

Giard

First:

Last:

@DavidGiard

2-Way Data Binding@Component({ selector: 'my-selector', template: `<h1>{{customer.FirstName}} Details</h1><div>First: <input [(ngModel)]="customer.LastName" </div><div>Last: <input [(ngModel)]="customer.FirstName" </div>`})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}

}Da Details

Da

Giard

First:

Last:

@DavidGiard

2-Way Data Binding@Component({ selector: 'my-selector', template: `<h1>{{customer.FirstName}} Details</h1><div>First: <input [(ngModel)]="customer.LastName" </div><div>Last: <input [(ngModel)]="customer.FirstName" </div>`})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}

}Dan Details

Dan

Giard

First:

Last:

@DavidGiard

Events binding<control (eventname)="methodname(parameters)">

click event<control (click)="methodtocall(parameters)">

e.g.,<div (click)="onClick(customer)">

@DavidGiard

click@Component({ selector: 'my-selector', template: `<h1 (click)="onClick (customer)">{{customer.FirstName}} Details</h1><div>First: <input [(ngModel)]="customer.LastName" </div><div>Last: <input [(ngModel)]="customer.FirstName" </div>`})export class DemoComponent {

id=1;customer: Customer = {FirstName='David';LastName='Giard';}onClick(cust: Customer) { alert ("You Selected " + customer.FirstName); }

}

@DavidGiard

Bootstrapping your Angular app

@DavidGiard

@Component({ selector: 'my-app', templateurl: 'myApp.html'})export class AppComponent { }

Bootstrapping

<script>…System.import('app')</script>

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

bootstrap(AppComponent);Main.ts

= bootstrap file

<my-app>Loading...</my-app>

@DavidGiard

Directives

@DavidGiard

Directives• Allow you to attach behavior to DOM elements

@DavidGiard

Directives• *ngFor• *ngIf• ngSwitch• ngClass• Custom Directives

@DavidGiard

*ngfor

<div *ngFor="#cust of customers"> {{cust.lastName}}, {{cust.firstName}}</div>

var customers: Customer[] = [ { "id": 1, "firstName": " Satya", "lastName" : " Nadella" }, { "id": 2, "firstName": "Bill", "lastName": "Gates" }, { "id": 3, "firstName": "Steve", "lastName": "Ballmer" }, { "id": 4, "firstName": " David ", "lastName": " Giard " }];

Nadella, SatyaGates, BillBallmer, SteveGiard, David

@DavidGiard

*ngIf• Syntax: *ngif="condition"• Removes element from DOM if condition is not “truthy”

@DavidGiard

*ngIf<h1>People I hate:</div><div *ngIf=“true”>

David Giard</div>

People I hate:David Giard

<h1>People I hate:</div><div *ngIf=“false”>

David Giard</div>

People I hate:

@DavidGiard

*ngIf

<div><button (click)="clicked()">Toggle</button><div *ngIf="show">

Can you see me?</div>

</div>

export class DemoComponent {show: boolean = true;clicked() {this.show = !this.show; }

}

ToggleCan you see me?

@DavidGiard

*ngIf

<div><button (click)="clicked()">Toggle</button><div *ngIf="show">

Can you see me?</div>

</div>

export class DemoComponent {show: boolean = true;clicked() {this.show = !this.show; }

}

ToggleCan you see me?

@DavidGiard

LifeCycle Hooks• OnInit• OnChanges• OnDestroy

@DavidGiard

OnInit

export class foo implements OnInit {...ngOnInit(){...}

}

@DavidGiard

Services

@DavidGiard

Services• Class containing logic• Shared Code: Used by components or other services• Substitutable Objects• Dependency Injection

@DavidGiard

Servicesimport { Injectable } from '@angular/core';

@Injectable()export class CustService { getCustomers() { return customers; }}

var customers: Customer[] = [ { "id": 1, "firstname": "David", "lastname": "Giard" }, { "id": 2, "firstname": "Bill", "lastname": "Gates" }, { "id": 3, "firstname": "Steve", "lastname": "Ballmer" }, { "id": 4, "firstname": "Satya", "lastname": "Nadella" }];

CustomerService.ts

@DavidGiard

Servicesimport { Injectable } from '@angular/core';

@Injectable()export class CustService { getCustomers() { return customers; }}…

CustomerService.ts

import { OnInit } from '@angular/core';import {CustService} from CustomerService

@Component({ selector: 'xxx',

template: 'yyy',…providers: [CustService]

})export class DemoComponent implements OnInit {

constructor(private customerService:CustService) { }

ngOnInit() { this.customers = this.customerService.getCustomers(); }

}

@DavidGiard

Routing

@DavidGiard

Routing• Load components dynamically into page• Link via URL• Client-side• Step 1: Bootstrap array of routes

@DavidGiard

Routinghttp://url.com/

HOME

---

---

---

---

@DavidGiard

Routinghttp://url.com/about

---

---

---

--- ABOUT

@DavidGiard

Routinghttp://url.com/products

---

---

---

--- PRODUCTS

@DavidGiard

Routingconst routes: Routes = [ {

path: foo', component: FooComponent

}, {

path: ‘bar', component: BarComponent

},];

<a [routerLink]="[/foo']">Foo</a><a [routerLink]="[/bar']">Bar</a>

<router-outlet></router-outlet>

app.routes.ts

User clicks “Foo” link

FooComponent loaded in router-outlet

@DavidGiard

HTTP

import {Http } from '@angular/http';

...

this.http.get(webServiceUrl);

bootstrap(DemoComponent, [HTTP_PROVIDERS,

]);

main.ts

Component

@DavidGiard

Observables (via RxJs)

Observable<T>

Function

Subscribe

Data

@DavidGiard

ObservablesgetCustomers(): Observable<customer[]> { return Observable.create((observer: Observer<any>) => { … observer.next(this.customers); })}

this.episodeService. getCustomers().subscribe((data) => {…

}

@DavidGiard

DEMO