An Introduction to Angular2

An Introduction to Angular2

Linux Tage Wien (Vienna, Austria)

source code: https://github.com/duffleit/LinuxWochen

E6c61f085d7aceaf97b7bd00e9195514?s=128

SQUER Solutions

April 30, 2016
Tweet

Transcript

  1. None
  2. dufeit Christoph Lindmaier christoph.lindmaier@techtalk.at David Leitner davidleitner@techtalk.at

  3. Tooling

  4. Entstehung von JS • 10 Tage • Brendan Eich •

    Standard durch ECMA • Laufzeitumgebung = Browser Mocha LiveScript
  5. 1. Generation • Libraries • Toolkits

  6. 2. Generation • Client-Side MVC • Applicaton Structure • Data

    Binding
  7. 3. Generation • Complete Client Side • Applicaton Development

  8. Google Javascript Frameworks • Angular 2 in Beta • Geschrieben

    in Typescript
  9. Features Angular 2 • Speed & Performance • Simple &

    Expressive • Cross Platorm • Routng • Dependency Injecton
  10. AngularJS 1 -> Angular2 • Ziele mit AngularJs 1 nicht

    erreichbar  Neues Framework • Binding • Dependency Injecton • Modularität • Performance
  11. None
  12. Typescript • Open Source • Transpilieren zu JavaScript • Source

    Maps • Typen • Module • Typ Inferenz • Klassen, Interfaces
  13. NPM • Package Manager • CLI Commands • Buildtool

  14. Setup Angular 2 • package.json • Angular 2 dependencies •

    Dev dependencies • tsconfg.json • Confg fle für Typescript
  15. package.json Name und Version der Applikaton

  16. Typescript transpilieren und Lite-Server starten package.json

  17. Typescript Compiler einmal ausführen package.json

  18. Typescript Compiler im Watch-Modus ausführen package.json

  19. Angular 2 Version package.json

  20. Universal dynamic module loader package.json

  21. Diverse Bibliotheken die von Angular benötgt werden package.json

  22. Dependencies die während der Entwicklung benötgt werden package.json

  23. Zu EcmaScript 5 Standard JavaScript Code transipilieren tsconfg.json

  24. Sourcemap ist Bindeglied zwischen JavaScript und TypeScript Code sehr hilfreich

    beim Debuggen tsconfg.json
  25. Angular2

  26. index.html bootstrapper.ts [METADATA] component.ts

  27. <html> <head> <title>Angular 2 QuickStart</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link

    rel="stylesheet" href="styles/styles.css"> <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script> <script... /> <!-- 2. Configure SystemJS --> <script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/bootstrapper') .then(null, console.error.bind(console)); </script> </head> <body> <lw-app>Loading...</lw-app> </body> </html> Einstegspunkt für Angular Komponente index.html
  28. index.html <html> <head> <title>Angular 2 QuickStart</title> <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="styles/styles.css"> <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script... /> <!-- 2. Configure SystemJS --> <script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/bootstrapper') .then(null, console.error.bind(console)); </script> </head> <body> <lw-app>Loading...</lw-app> </body> </html> SystemJS Module Loader System.import('module to import') C#: using JAVA: import
  29. index.html import {bootstrap} from 'angular2/platform/browser'; import {Main} from './lw.componente'; bootstrap(Main);

    <html> <head> <title>Angular 2 QuickStart</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="styles/styles.css"> <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script... /> <!-- 2. Configure SystemJS --> <script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/bootstrapper') .then(null, console.error.bind(console)); </script> </head> <body> <lw-app>Loading...</lw-app> </body> </html> bootstrapper.ts
  30. import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: ` <div

    class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] } Decorator Component component.ts
  31. Html-Tag component.ts import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template:

    ` <div class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] }
  32. import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: ` <div

    class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] } component.ts
  33. import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: ` <div

    class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] } component.ts
  34. component.ts Binding import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template:

    ` <div class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] }
  35. component.ts ngFor Binding •ngIf •ngSwitch •ngClass import {Component} from 'angular2/core';

    @Component({ selector: 'lw-app', template: ` <div class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] }
  36. component.ts ngFor Binding import {Component} from 'angular2/core'; @Component({ selector: 'lw-app',

    template: ` <div class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersionen"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] }
  37. component.ts Method Binding import {Component} from 'angular2/core'; @Component({ selector: 'lw-app',

    template: ` <div class="linuxVersions"> <h1>{{title}}</h1> <input (click)="addYear()" type="button" value="add year to title"/> </div> ` }) export class Main { public title = "LinuxVersions"; public addYear(){ var currentYear = this.getCurrentYear(); this.title = "LinuxVersion in " + currentYear; } private getCurrentYear() : number { return (new Date()).getFullYear(); } }
  38. component.ts import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: `

    <div class="linuxVersions"> <h1>{{title}}</h1> <input (click)="addYear()" type="button" value="add year to title"/> </div> ` }) export class Main { public title = "LinuxVersions"; public addYear(){ var currentYear = this.getCurrentYear(); this.title = "LinuxVersion in " + currentYear; } private getCurrentYear() : number { return (new Date()).getFullYear(); } }
  39. component.ts import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: `

    <div class="linuxVersions"> <h1>{{title}}</h1> <div><input type="text" [(ngModel)]="title" ></div> <div><input (click)="addYear()" type="button" value="add year to title"/></div> </div> ` }) export class Main { public title = "LinuxVersionen"; public addYear(){ var currentYear = this.getCurrentYear(); this.title = "LinuxVersion in " + currentYear; } private getCurrentYear() : number { return (new Date()).getFullYear(); } } Two-Way Binding
  40. component.ts import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: `

    <div class="linuxVersions"> <h1>{{title}}</h1> <div><input type="text" [(ngModel)]="title" ></div> <div><input (click)="addYear()" type="button" value="add year to title"/></div> </div> ` }) export class Main { public title = "LinuxVersionen"; public addYear(){ var currentYear = this.getCurrentYear(); this.title = "LinuxVersion in " + currentYear; } private getCurrentYear() : number { return (new Date()).getFullYear(); } }
  41. import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: ` <div

    class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] } component.ts
  42. import {Component} from 'angular2/core'; @Component({ selector: 'lw-app', template: ` <div

    class="linuxVersions"> <h1>{{title}}</h1> <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> </div> ` }) export class Main { public title = "LinuxVersions"; public versions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] } component.ts Template: templateUrl: 'pathToTemplate.html'
  43. index.html bootstrapper.ts component.ts

  44. index.html bootstrapper.ts component.ts service.ts [DI]

  45. service.ts import {Injectable} from 'angular2/core' import {LinuxVersion} from "./linuxVersion"; @Injectable()

    export class LinuxVersionService{ private linuxVersions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] getCurrentLinuxVersions() : Array<LinuxVersion>{ //this would probably call a webservice return this.linuxVersions; } addLinuxVersion(name: string, version: string) : void { this.linuxVersions.push({ name: name, number: version }); } }
  46. service.ts export interface LinuxVersion{ name: string; number: string; } import

    {Injectable} from 'angular2/core' import {LinuxVersion} from "./linuxVersion"; @Injectable() export class LinuxVersionService{ private linuxVersions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] getCurrentLinuxVersions() : Array<LinuxVersion>{ //this would probably call a webservice return this.linuxVersions; } addLinuxVersion(name: string, version: string) : void { this.linuxVersions.push({ name: name, number: version }); } }
  47. service.ts import {Injectable} from 'angular2/core' import {LinuxVersion} from "./linuxVersion"; @Injectable()

    export class LinuxVersionService{ private linuxVersions = [ { name: "Ubuntu", number: "1604"}, { name: "Linux Mint", number: "17.3"}, { name: "ElementaryOS", number: "0.3.2"}, { name: "Fedora", number: "23"} ] getCurrentLinuxVersions() : LinuxVersion[]{ //this would probably call a webservice return this.linuxVersions; } addLinuxVersion(name: string, version: string) : void { this.linuxVersions.push({ name: name, number: version }); } } = Singleton
  48. Component.ts import {Component} from 'angular2/core'; import {LinuxVersionService} from "./LinuxVersionService"; import

    {LinuxVersion} from "./linuxVersion"; @Component({ selector: 'lw-app', template: ` <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> `, providers: [LinuxVersionService] }) export class Main { constructor(private _linuxVersionService: LinuxVersionService) { } get versions():Array<LinuxVersion> { return this._linuxVersionService.getCurrentLinuxVersions(); } }
  49. import {Component} from 'angular2/core'; import {LinuxVersionService} from "./LinuxVersionService"; import {LinuxVersion}

    from "./linuxVersion"; @Component({ selector: 'lw-app', template: ` <ul *ngFor="#version of versions"> <li> <span class="version-name">{{version.name}}</span> <span class="version-number">{{version.number}}</span> </li> </ul> `, providers: [LinuxVersionService] }) export class Main { constructor(private _linuxVersionService: LinuxVersionService) { } get versions():Array<LinuxVersion> { return this._linuxVersionService.getCurrentLinuxVersions(); } } Component.ts versions : Array<LinuxVersion>; get version(): Array<LinuxVersion> { return ... } set version(): Array<LinuxVersion> { ... = value; }
  50. index.html bootstrapper.ts component.ts service.ts [DI]

  51. index.html detail.ts service.ts [DI] master.ts /Master / Detail[id] bootstrapper.ts main.ts

  52. main.ts @Component({ selector: 'lw-app', template: ` <div class="linuxVersions"> <h1><a [routerLink]="['Versions']">{{title}}</a></h1>

    <router-outlet></router-outlet> </div> `, directives: [ROUTER_DIRECTIVES], providers: [ROUTER_PROVIDERS] }) @RouteConfig([ { path: '/detail/:id', name: 'VersionDetail', component: VersionDetailComponent, }, { path: '/versions', name: 'Versions', component: VersionsComponent, useAsDefault: true } ]) export class Main { public title = "LinuxVersionen"; }
  53. main.ts @Component({ selector: 'lw-app', template: ` <div class="linuxVersions"> <h1><a [routerLink]="['Versions']">{{title}}</a></h1>

    <router-outlet></router-outlet> </div> `, directives: [ROUTER_DIRECTIVES], providers: [ROUTER_PROVIDERS] }) @RouteConfig([ { path: '/detail/:id', name: 'VersionDetail', component: VersionDetailComponent, }, { path: '/versions', name: 'Versions', component: VersionsComponent, useAsDefault: true } ]) export class Main { public title = "LinuxVersionen"; }
  54. master.ts @Component({ selector: 'lw-versions', template: ` <ul *ngFor="#version of versions">

    <li> <span class="version-number">{{version.number}}</span> <span class="version-name">{{version.name}}</span> <a (click)="getDetail(version)">get Details</a> </li> </ul> `, providers: [LinuxVersionService, ROUTER_PROVIDERS] }) export class VersionsComponent { constructor( private _router : Router, private _linuxVersionService: LinuxVersionService ) { } get versions():Array<LinuxVersion> { return this._linuxVersionService.getCurrentLinuxVersions(); } getDetail(version: LinuxVersion) { this._router.navigate(['VersionDetail', { id: version.id }]); } }
  55. detail.ts @Component({ selector: 'lw-version-detail', template: ` <div><b>Name</b> {{version.name}}</div> <div><b>Number</b> {{version.number}}</div>

    <div><b>Id</b> {{version.id}}</div> `, providers: [LinuxVersionService] }) export class VersionDetailComponent implements OnInit{ version : LinuxVersion; constructor(private _linuxVersionService: LinuxVersionService, private _routeParams: RouteParams) { } ngOnInit() { let id = +this._routeParams.get('id'); this.version = this._linuxVersionService.getLinuxVersion(id) } }
  56. detail.ts @Component({ selector: 'lw-version-detail', template: ` <div><b>Name</b> {{version.name}}</div> <div><b>Number</b> {{version.number}}</div>

    <div><b>Id</b> {{version.id}}</div> `, providers: [LinuxVersionService] }) export class VersionDetailComponent implements OnInit{ version : LinuxVersion; constructor(private _linuxVersionService: LinuxVersionService, private _routeParams: RouteParams) { } ngOnInit() { let id = this._routeParams.get('id'); this.version = this._linuxVersionService.getLinuxVersion(id) } } Lifecycle Hooks: •ngOnInit •ngOnChanges •ngOnDestroy •ngAferViewInit •ngDoCheck •…
  57. /Detail/0 /Versions index.html SinglePageApplicaton

  58. index.html detail.ts service.ts [DI] master.ts /Master / Detail[id] bootstrapper.ts main.ts

  59. index.html detail.ts service.ts [DI] master.ts /Master / Detail[id] bootstrapper.ts main.ts

    specs.ts Tests Test Runner
  60. service.spec.ts import { LinuxVersionService } from '../app/linuxVersionService'; import {describe, it,

    beforeEach, expect} from 'angular2/testing'; describe('LinuxVersionService', () => { var linuxVersionService: LinuxVersionService = null; beforeEach(()=>{ linuxVersionService = new LinuxVersionService(); }); it('can add linuxVersion', () => { let expectedVersionCount = linuxVersionService.getCurrentLinuxVersions().length + 1; linuxVersionService.addLinuxVersion('Debian', '8.4 Jessie'); let actualVersionCount = linuxVersionService.getCurrentLinuxVersions().length; expect(actualVersionCount).toEqual(expectedVersionCount); }); it('can find linuxVersionById', () => { let addedVersionId = linuxVersionService.addLinuxVersion('Debian', '8.4 Jessie'); var linuxVersion = linuxVersionService.getLinuxVersion(addedVersionId); expect(linuxVersion.name).toEqual('Debian'); expect(linuxVersion.number).toEqual('8.4 Jessie'); }); });
  61. import { LinuxVersionService } from '../app/linuxVersionService'; import {describe, it, beforeEach,

    expect} from 'angular2/testing'; describe('LinuxVersionService', () => { var linuxVersionService: LinuxVersionService = null; beforeEach(()=>{ linuxVersionService = new LinuxVersionService(); }); it('can add linuxVersion', () => { let expectedVersionCount = linuxVersionService.getCurrentLinuxVersions().length + 1; linuxVersionService.addLinuxVersion('Debian', '8.4 Jessie'); let actualVersionCount = linuxVersionService.getCurrentLinuxVersions().length; expect(actualVersionCount).toEqual(expectedVersionCount); }); it('can find linuxVersionById', () => { let addedVersionId = linuxVersionService.addLinuxVersion('Debian', '8.4 Jessie'); var linuxVersion = linuxVersionService.getLinuxVersion(addedVersionId); expect(linuxVersion.name).toEqual('Debian'); expect(linuxVersion.number).toEqual('8.4 Jessie'); }); }); service.spec.ts
  62. import { LinuxVersionService } from '../app/linuxVersionService'; import {describe, it, beforeEach,

    expect} from 'angular2/testing'; describe('LinuxVersionService', () => { var linuxVersionService: LinuxVersionService = null; beforeEach(()=>{ linuxVersionService = new LinuxVersionService(); }); it('can add linuxVersion', () => { let expectedVersionCount = linuxVersionService.getCurrentLinuxVersions().length + 1; linuxVersionService.addLinuxVersion('Debian', '8.4 Jessie'); let actualVersionCount = linuxVersionService.getCurrentLinuxVersions().length; expect(actualVersionCount).toEqual(expectedVersionCount); }); it('can find linuxVersionById', () => { let addedVersionId = linuxVersionService.addLinuxVersion('Debian', '8.4 Jessie'); var linuxVersion = linuxVersionService.getLinuxVersion(addedVersionId); expect(linuxVersion.name).toEqual('Debian'); expect(linuxVersion.number).toEqual('8.4 Jessie'); }); }); service.spec.ts
  63. testrunner.html <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>Ng App

    Unit Tests</title> <link rel="stylesheet" href="/node_modules/jasmine-core/lib/jasmine-core/jasmine.css"> <script src="/node_modules/es6-shim/es6-shim.min.js"></script> ... <script src="/node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script> <script src="/node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script> <script src="/node_modules/jasmine-core/lib/jasmine-core/boot.js"></script> </head> <body> <script> System.config({ packages: { 'app': {defaultExtension: 'js'} } }); System.import('app/linuxVersionService.spec') .then(window.onload) .catch(console.error.bind(console)); </script> </body> </html>
  64. index.html detail.ts service.ts [DI] master.ts /Master / Detail[id] bootstrapper.ts main.ts

    specs.ts Tests Test Runner
  65. None