The First Step to
Angular 2

@laco0416

2016/9/3 HTML5 Conference

about me

Developing an Angular 2 Edge

http://shop.oreilly.com/product/9781939902375.do

Agenda

  • Angular 2 Overview
  • Final APIs
  • Angular 2 Router

Angular 2

  • Web Standards
  • Simple
  • Fast
  • Full-stack
  • Powered by

Web Standards Friendly

  • ECMAScript 2015 
  • Web Worker
  • Decorators
  • Web Animations API
  • Web Components
  • Fetch API
  • Observables
  • Zones

Component definition

@Component({
    selector: "app-profile",
    template: "<p>Name: {{ name }}</p>"
})
class ProfileComponent {
    @Input() name: string;
}
<div>
    <app-profile name="laco"></app-profile>
</div>

Template Syntax (1)

Data-Binding: [prop]

@Component({
    template: `
    <input [value]="name"> 
    <div [attr.role]="role"></div>
    <div [class.large]="isLarge"></div>
    <div [style.width.px]="mySize"></div>
    `
})
class MyComponent {
    name = "laco";
    role = "main"
    isLarge = true;
    mySize = 16;
}

Template Syntax (2)

Event Handling: (event)

@Component({
    template: `
    <button (click)="onClick($event)">
    `
})
class MyComponent {
    onClick(e: MouseEvent) {
    }
}

High Performance

  • Smart Change Detector
  • One-way Checking
  • 100000 checks / 10ms

Official Packages

  • @angular/core

  • @angular/forms

  • @angular/http

  • @angular/router

  • Testing

  • Angular Material

  • Angular Universal: Server side

  • AngularFire: Firebase

TypeScript

  • Static Type
  • Decorators
  • Type-base Dependency Injection

Static Types

Types as API documents

  • Always correct

  • Compiler check

  • Auto-completions

@Decorators()

Next generation standard

Spec: javascript-decorators
Status: tc39/proposals

  • Class and Property: Stage 2
  • Function: Stage 0
  • Method: Stage 0

tsc --experimentalDecorators

Type-base DI

IOW, "Typo-safe" DI

Good-bye "$http"

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

@Injectable()
class MyService {
    constructor(private anyNameForHttp: Http) {
    }
}

Angular 2 Final APIs

Basic APIs

  • @Component()

  • @Input() / @Output()

  • @Directive()

  • @Pipe()

  • @NgModule()

@Component

It's a component because it composes app

  • Component = Directive + Template

  • CSS Encapsulation

  • Build Component Tree

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

@Component({
    selector: 'my-app',
    template: `
    <h1>{{title}}</h1>
    `,
    styles: [`h1 { color: blue; }`]
})
export class MyAppComponent {
    title = 'Hello World!';
}

Demo

Component Tree

Top-down Data Flow: @Input()

@Component({
    selector: 'my-app',
    template: `<profile [name]="myName"></profile>`
})
class MyAppComponent {
    myName = 'laco';
}
@Component({
    selector: 'profile',
    template: `<p>{{name}}</p>`
})
class ProfileComponent {
    @Input() name;
}

Component Tree

Bottom-up Event System: @Output()

@Component({
    selector: 'my-app',
    template: `<app-menu (select)="onMenuSelect($event)"></app-menu>`
})
class MyAppComponent {
    onMenuSelect(menuItem) { }
}
@Component({
    selector: 'app-menu',
    template: `...`
})
class MenuComponent {
    @Output() select = new EventEmitter();

    selectMenu(menuItem) { this.select.emit(menuItem); }
}

@Directive

Extend elements

import {Directive, HostBinding} from '@angular/core';

@Directive({
    selector: '[bsBtnPrimary]'
})
class BootstrapBtn {
    @HostBinding('class') classNames = "btn btn-primary";
}
<button bsBtnPrimary>Primary Button</button>


<button class="btn btn-primary">Primary Button</button>

@Pipe

Data transformer

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

@Pipe({
    name: 'quote'
})
class QuotePipe {
    transform(value) {
        return `"${value}"`;
    }
}
<p>{{ message | quote }}</p>

Angular 2 Architecture

Module

Components

Application

Platform

Directives

Pipes

Angular Modules

Application Configuration

  • Import other modules

  • Create Compiler

  • Setup Injector

  • bootstrapping

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {MyAppComponent} from './app.component';
import {MyOtherComponent} from './other.component';
import {MyService} from './my.service';

@NgModule({
    imports: [BrowserModule],
    declarations: [MyOtherComponent, MyAppComponent],
    providers: [MyService],
    bootstrap: [MyAppComponent]
})
export class MyAppModule {}

Angular Platforms

Application Environment

  • Browser (JIT, AoT)

  • Web Worker

  • Server

import {
  platformBrowser
} from '@angular/platform-browser';
import {
  platformBrowserDynamic
} from '@angular/platform-browser-dynamic';
import {
  platformWorkerApp, platformWorkerUi
} from '@angular/platform-webworker';
import {
  platformServer, platformServerDynamic
} from '@angular/platform-server';

import {MyAppModule} from './app.module';

platformBrowserDynamic().bootstrapModule(MyAppModule);

Angular 2 Router

a long time ago...

2015 ng-conf: New Router

2015 AngularConnect: Component Router

2016 ng-conf Router v2

Router v3

Designer: @victorsavkin

  • One Configuration
  • One State
  • One-way URL Processing
  • Powered by RxJS

 

Route Configuration

path-component patterns

export const appRoutes = [
    // .../ 
    { path: '', pathMatch: 'full', component: HomeCmp },
    // .../about
    { path: 'about', component: AboutCmp },    
    { 
        // nested routes
        path: 'users', children: [
            // .../users
            { path: '', pathMatch: 'full', component: UserListCmp },
            // .../users/11
            { path: ':id', component: UserDetailCmp }
        ]
    },
    // wildcard route
    { path: '**', redirectTo: '/'}
]; 

Install Router

import RouterModule

import {RouterModule} from '@angular/router';
import {appRoutes} from './app.routes';

@NgModule({
    imports: [RouterModule.forRoot(appRoutes)],
})
class MyAppModule {}

Use Router

<router-outlet> & routerLink

@Component({
    template: `
    <nav>
        <a routerLink="/">Home</a> | 
        <a routerLink="/about">About</a>
    </nav>
    <main>
        <router-outlet></router-outlet>
    </main>
    `
})
export class MyAppComponent {}

Router v3 Architecture

Router State

ActivatedRoute 💖 Observable

@Component({
    template: `
    <nav>...</nav>
    <main>
        <router-outlet></router-outlet>
    </main>
    `
})
export class MyAppComponent {
    constructor(private route: ActivatedRoute) {
        route.url.subscribe(url => {
            console.log(`URL changed: ${url}`);
        });
    }
}

Router State

Async / Sync

// URL Changes
route.url.subscribe(...);

// Params (/users/:id)
route.params.subscribe(...);

// QueryParams (?foo=bar)
route.queryParams.subscribe(...);

// Fragment (#section1)
route.fragment.subscribe(...);

// Sync Snapshot 
route.snapshot.params['id'];

Demo

Conclusion

  • Angular 2 💖 Web Standards

  • Angular 2 💖 TypeScript

  • Simple & Useful APIs

  • Platform/Module/Component Tree

  • Router v3: Easy

Thanks!

The First Step to Angular 2

By Suguru Inatomi

The First Step to Angular 2

  • 7,281