Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Angular 2 - En introduksjon

Angular 2 - En introduksjon

Kristian Tryggestad

March 30, 2016
Tweet

Other Decks in Programming

Transcript

  1. INTRODUKSJON - AngularJS • Eksistert siden 2009 • API har

    blitt komplekst • Uheldig navngivning • Designet for en annen tid 2
  2. INTRODUKSJON Status: • 55 alpha-versjoner • 12 beta-versjoner • Release:

    ila. 2016 Angular 2 in the wild: • Google Fiber (released) • Google AdWords (Q1) • Weather.com (April) 3
  3. WHAT’S CHANGED? Filosofi: • Fast, Mobile, Flexible, (Modern) Features: •

    Fokus på utviklerverktøy • Zone.js • Unidirectional data flow • Components, components, components 4
  4. WHAT’S MISSING? • Animasjoner • I18n / l10n • Material

    Design • a11y • Cookie/storage handling • ngMessages • ngResource 5
  5. HELLO WORLD <!DOCTYPE html> <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.24/system-polyfills.js"></script>

    <script src="https://code.angularjs.org/2.0.0-beta.9/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/tools/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/angular2.dev.js"></script> <script> System.config({ transpiler: "typescript", typescriptOptions: { emitDecoratorMetadata: true }, packages: {"app": {defaultExtension: "ts"}} }); System.import("app/app.component"); </script> </head> <body> <my-app>Loading...</my-app> </body> </html> index.html 6
  6. HELLO WORLD <!DOCTYPE html> <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.24/system-polyfills.js"></script>

    <script src="https://code.angularjs.org/2.0.0-beta.9/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/tools/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/angular2.dev.js"></script> <script> System.config({ transpiler: "typescript", typescriptOptions: { emitDecoratorMetadata: true }, packages: {"app": {defaultExtension: "ts"}} }); System.import("app/app.component"); </script> </head> <body> <my-app>Loading...</my-app> </body> </html> index.html 7
  7. HELLO WORLD <!DOCTYPE html> <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.24/system-polyfills.js"></script>

    <script src="https://code.angularjs.org/2.0.0-beta.9/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/tools/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/angular2.dev.js"></script> <script> System.config({ transpiler: "typescript", typescriptOptions: { emitDecoratorMetadata: true }, packages: {"app": {defaultExtension: "ts"}} }); System.import("app/app.component"); </script> </head> <body> <my-app>Loading...</my-app> </body> </html> index.html 8
  8. HELLO WORLD <!DOCTYPE html> <html> <head> <script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.0/es6-shim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.24/system-polyfills.js"></script>

    <script src="https://code.angularjs.org/2.0.0-beta.9/angular2-polyfills.js"></script> <script src="https://code.angularjs.org/tools/system.js"></script> <script src="https://code.angularjs.org/tools/typescript.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/Rx.js"></script> <script src="https://code.angularjs.org/2.0.0-beta.9/angular2.dev.js"></script> <script> System.config({ transpiler: "typescript", typescriptOptions: { emitDecoratorMetadata: true }, packages: {"app": {defaultExtension: "ts"}} }); System.import("app/app.component"); </script> </head> <body> <my-app>Loading...</my-app> </body> </html> index.html 9
  9. HELLO WORLD import {bootstrap} from "angular2/platform/browser"; import {Component} from "angular2/core";

    @Component({ selector: "my-app", template: "Hello World!", }) export class AppComponent {} bootstrap(AppComponent); app.component.ts form:not([ngNoForm]):not([ngFormModel]),ngForm,[ngForm] 10
  10. VIEW SYNTAX import {Component} from "angular2/core"; @Component({ selector: "my-app", template:

    ` <button type="button" (click)="toggleVisibility()">Magic</button> <p [hidden]=“!isVisible">I will be hidden</p> <div *ngIf="isVisible">I will be removed from the DOM</div> ` }) export class AppComponent { isVisible = true; toggleVisibility() { this.isVisible = !this.isVisible; } } app.component.ts 11
  11. VIEW SYNTAX import {Component} from "angular2/core"; @Component({ selector: "my-app", template:

    ` <button type="button" (click)="toggleVisibility()">Magic</button> <p [hidden]=“!isVisible">I will be hidden</p> <div *ngIf="isVisible">I will be removed from the DOM</div> ` }) export class AppComponent { isVisible = true; toggleVisibility() { this.isVisible = !this.isVisible; } } app.component.ts 12
  12. VIEW SYNTAX import {Component} from "angular2/core"; @Component({ selector: "my-app", template:

    ` <button type="button" (click)="toggleVisibility()">Magic</button> <p [hidden]=“!isVisible">I will be hidden</p> <div *ngIf="isVisible">I will be removed from the DOM</div> ` }) export class AppComponent { isVisible = true; toggleVisibility() { this.isVisible = !this.isVisible; } } app.component.ts 13
  13. VIEW SYNTAX import {Component} from "angular2/core"; @Component({ selector: "my-app", template:

    ` <button type="button" (click)="toggleVisibility()">Magic</button> <p [hidden]=“!isVisible">I will be hidden</p> <div *ngIf="isVisible">I will be removed from the DOM</div> ` }) export class AppComponent { isVisible = true; toggleVisibility() { this.isVisible = !this.isVisible; } } app.component.ts 14
  14. VIEW SYNTAX import {Component} from "angular2/core"; @Component({ selector: "my-app", template:

    ` <button type="button" (click)="toggleVisibility()">Magic</button> <p [hidden]=“!isVisible">I will be hidden</p> <div *ngIf="isVisible">I will be removed from the DOM</div> ` }) export class AppComponent { isVisible = true; toggleVisibility() { this.isVisible = !this.isVisible; } } app.component.ts 15
  15. DI & LOCAL VARIABLES export interface Entry { name: string;

    } export class EntryService { entries: Entry[] = [ { name: "First entry" }, { name: "Second entry" } ]; addEntry(entry: Entry) { this.entries.push(entry); } } entry.service.ts 16
  16. DI & LOCAL VARIABLES import {Component} from "angular2/core"; import {EntryService,

    Entry} from "./entry.service"; @Component({ selector: "my-app", template: `...`, providers: [EntryService] }) export class AppComponent { entries: Entry[]; constructor(private entryService: EntryService) { this.entries = entryService.entries; } addEntry(name: string) { const entry: Entry = { name }; this.entryService.addEntry(entry); } } <h2>Add entry - {{entryField.value || "Unnamed"}}</h2> <input type="text" #entryField (keyup)="0"> <button type="button" (click)="addEntry(entryField.value)"> Add </button> <h2>Entries</h2> <ul> <li *ngFor="#entry of entries">{{entry.name}}</li> </ul> app.component.ts 17
  17. DI & LOCAL VARIABLES import {Component} from "angular2/core"; import {EntryService,

    Entry} from "./entry.service"; @Component({ selector: "my-app", template: `...`, providers: [EntryService] }) export class AppComponent { entries: Entry[]; constructor(private entryService: EntryService) { this.entries = entryService.entries; } addEntry(name: string) { const entry: Entry = { name }; this.entryService.addEntry(entry); } } <h2>Add entry - {{entryField.value || "Unnamed"}}</h2> <input type="text" #entryField (keyup)="0"> <button type="button" (click)="addEntry(entryField.value)"> Add </button> <h2>Entries</h2> <ul> <li *ngFor="#entry of entries">{{entry.name}}</li> </ul> app.component.ts 18
  18. DI & LOCAL VARIABLES import {Component} from "angular2/core"; import {EntryService,

    Entry} from "./entry.service"; @Component({ selector: "my-app", template: `...`, providers: [EntryService] }) export class AppComponent { entries: Entry[]; constructor(private entryService: EntryService) { this.entries = entryService.entries; } addEntry(name: string) { const entry: Entry = { name }; this.entryService.addEntry(entry); } } <h2>Add entry - {{entryField.value || "Unnamed"}}</h2> <input type="text" #entryField (keyup)="0"> <button type="button" (click)="addEntry(entryField.value)"> Add </button> <h2>Entries</h2> <ul> <li *ngFor="#entry of entries">{{entry.name}}</li> </ul> app.component.ts 19
  19. DI & LOCAL VARIABLES import {Component} from "angular2/core"; import {EntryService,

    Entry} from "./entry.service"; @Component({ selector: "my-app", template: `...`, providers: [EntryService] }) export class AppComponent { entries: Entry[]; constructor(private entryService: EntryService) { this.entries = entryService.entries; } addEntry(name: string) { const entry: Entry = { name }; this.entryService.addEntry(entry); } } <h2>Add entry - {{entryField.value || "Unnamed"}}</h2> <input type="text" #entryField (keyup)="0"> <button type="button" (click)="addEntry(entryField.value)"> Add </button> <h2>Entries</h2> <ul> <li *ngFor="#entry of entries">{{entry.name}}</li> </ul> app.component.ts 20
  20. DI & LOCAL VARIABLES import {Component} from "angular2/core"; import {EntryService,

    Entry} from "./entry.service"; @Component({ selector: "my-app", template: `...`, providers: [EntryService] }) export class AppComponent { entries: Entry[]; constructor(private entryService: EntryService) { this.entries = entryService.entries; } addEntry(name: string) { const entry: Entry = { name }; this.entryService.addEntry(entry); } } <h2>Add entry - {{entryField.value || "Unnamed"}}</h2> <input type="text" #entryField (keyup)="0"> <button type="button" (click)="addEntry(entryField.value)"> Add </button> <h2>Entries</h2> <ul> <li *ngFor="#entry of entries">{{entry.name}}</li> </ul> app.component.ts 21
  21. CHILD COMPONENTS import {Component} from "angular2/core"; import {EntryService, Entry} from

    "./entry.service"; import {EntryComponent} from "./entry.component"; @Component({ selector: "my-app", template: `...`, providers: [EntryService], directives: [EntryComponent], styles: [".is-selected {color: red}"] }) export class AppComponent { entries: Entry[]; selectedEntry: Entry; constructor(entryService: EntryService) { this.entries = entryService.entries; } } <h2>Entries</h2> <ul> <li *ngFor="#entry of entries" [class.is-selected]="selectedEntry === entry"> <entry [model]="entry" (selected)="selectedEntry = $event"></entry> </li> </ul> app.component.ts 22
  22. CHILD COMPONENTS import {Component} from "angular2/core"; import {EntryService, Entry} from

    "./entry.service"; import {EntryComponent} from "./entry.component"; @Component({ selector: "my-app", template: `...`, providers: [EntryService], directives: [EntryComponent], styles: [".is-selected {color: red}"] }) export class AppComponent { entries: Entry[]; selectedEntry: Entry; constructor(entryService: EntryService) { this.entries = entryService.entries; } } <h2>Entries</h2> <ul> <li *ngFor="#entry of entries" [class.is-selected]="selectedEntry === entry"> <entry [model]="entry" (selected)="selectedEntry = $event"></entry> </li> </ul> app.component.ts 23
  23. CHILD COMPONENTS import {Component} from "angular2/core"; import {EntryService, Entry} from

    "./entry.service"; import {EntryComponent} from "./entry.component"; @Component({ selector: "my-app", template: `...`, providers: [EntryService], directives: [EntryComponent], styles: [".is-selected {color: red}"] }) export class AppComponent { entries: Entry[]; selectedEntry: Entry; constructor(entryService: EntryService) { this.entries = entryService.entries; } } <h2>Entries</h2> <ul> <li *ngFor="#entry of entries" [class.is-selected]="selectedEntry === entry"> <entry [model]="entry" (selected)="selectedEntry = $event"></entry> </li> </ul> app.component.ts 24
  24. CHILD COMPONENTS import {Component, Input, Output, EventEmitter} from "angular2/core"; import

    {Entry} from "./entry.service"; @Component({ selector: "entry", template: ` <div role="button" (click)="selected.emit(model)" [attr.aria-hidden]="false"> {{model.name}} </div> ` }) export class EntryComponent { @Input() model: Entry; @Output() selected = new EventEmitter(); } entry.component.ts 25
  25. CHILD COMPONENTS import {Component, Input, Output, EventEmitter} from "angular2/core"; import

    {Entry} from "./entry.service"; @Component({ selector: "entry", template: ` <div role="button" (click)="selected.emit(model)" [attr.aria-hidden]="false"> {{model.name}} </div> ` }) export class EntryComponent { @Input() model: Entry; @Output() selected = new EventEmitter(); } entry.component.ts 26
  26. CHILD COMPONENTS import {Component, Input, Output, EventEmitter} from "angular2/core"; import

    {Entry} from "./entry.service"; @Component({ selector: "entry", template: ` <div role="button" (click)="selected.emit(model)" [attr.aria-hidden]="false"> {{model.name}} </div> ` }) export class EntryComponent { @Input() model: Entry; @Output() selected = new EventEmitter(); } entry.component.ts 27
  27. CHILD COMPONENTS import {Component, Input, Output, EventEmitter} from "angular2/core"; import

    {Entry} from "./entry.service"; @Component({ selector: "entry", template: ` <div role="button" (click)="selected.emit(model)" [attr.aria-hidden]="false"> {{model.name}} </div> ` }) export class EntryComponent { @Input() model: Entry; @Output() selected = new EventEmitter(); } entry.component.ts 28
  28. FORMS import {Component} from "angular2/core"; import {FormBuilder, ControlGroup, Validators} from

    "angular2/common"; @Component({ selector: "my-app", template: `...` }) export class AppComponent { name = "Kristian"; myForm: ControlGroup; constructor(fb: FormBuilder) { this.myForm = fb.group({ "name": ["Kristian", Validators.required] }); } onSubmit(values: any) { console.log(values.name); } } <input type="text" [(ngModel)]="name"> <p>Hello {{name}}</p> <form #f="ngForm" (ngSubmit)="onSubmit(f.value)"> <input type="text" ngControl="name"> <button type="submit">Submit</button> </form> <form [ngFormModel]="myForm" (ngSubmit)="onSubmit(myForm.value)"> <input type="text" [ngFormControl]="myForm.controls['name']"> <button type="submit" [disabled]="!myForm.valid">Submit</button> </form> app.component.ts 29
  29. FORMS import {Component} from "angular2/core"; import {FormBuilder, ControlGroup, Validators} from

    "angular2/common"; @Component({ selector: "my-app", template: `...` }) export class AppComponent { name = "Kristian"; myForm: ControlGroup; constructor(fb: FormBuilder) { this.myForm = fb.group({ "name": ["Kristian", Validators.required] }); } onSubmit(values: any) { console.log(values.name); } } <input type="text" [(ngModel)]="name"> <p>Hello {{name}}</p> <form #f="ngForm" (ngSubmit)="onSubmit(f.value)"> <input type="text" ngControl="name"> <button type="submit">Submit</button> </form> <form [ngFormModel]="myForm" (ngSubmit)="onSubmit(myForm.value)"> <input type="text" [ngFormControl]="myForm.controls['name']"> <button type="submit" [disabled]="!myForm.valid">Submit</button> </form> app.component.ts 30
  30. FORMS import {Component} from "angular2/core"; import {FormBuilder, ControlGroup, Validators} from

    "angular2/common"; @Component({ selector: "my-app", template: `...` }) export class AppComponent { name = "Kristian"; myForm: ControlGroup; constructor(fb: FormBuilder) { this.myForm = fb.group({ "name": ["Kristian", Validators.required] }); } onSubmit(values: any) { console.log(values.name); } } <input type="text" [(ngModel)]="name"> <p>Hello {{name}}</p> <form #f="ngForm" (ngSubmit)="onSubmit(f.value)"> <input type="text" ngControl="name"> <button type="submit">Submit</button> </form> <form [ngFormModel]="myForm" (ngSubmit)="onSubmit(myForm.value)"> <input type="text" [ngFormControl]="myForm.controls['name']"> <button type="submit" [disabled]="!myForm.valid">Submit</button> </form> app.component.ts 31
  31. FORMS import {Component} from "angular2/core"; import {FormBuilder, ControlGroup, Validators} from

    "angular2/common"; @Component({ selector: "my-app", template: `...` }) export class AppComponent { name = "Kristian"; myForm: ControlGroup; constructor(fb: FormBuilder) { this.myForm = fb.group({ "name": ["Kristian", Validators.required] }); } onSubmit(values: any) { console.log(values.name); } } <input type="text" [(ngModel)]="name"> <p>Hello {{name}}</p> <form #f="ngForm" (ngSubmit)="onSubmit(f.value)"> <input type="text" ngControl="name"> <button type="submit">Submit</button> </form> <form [ngFormModel]="myForm" (ngSubmit)="onSubmit(myForm.value)"> <input type="text" [ngFormControl]="myForm.controls['name']"> <button type="submit" [disabled]="!myForm.valid">Submit</button> </form> app.component.ts 32
  32. EKSEMPLER • Hello World http://plnkr.co/edit/8z8ZinVi19UbEvSr77OW • View Syntax http://plnkr.co/edit/VO40tsmJEaa0vWXPm00M •

    DI & Local vars http://plnkr.co/edit/dawjk1EUacubwbPrJvz4 • Child components http://plnkr.co/edit/IkfBUPdxESIdDeX8jeM7 • Forms http://plnkr.co/edit/scCWNoyaCq9zMvDBNOD7 • Parent/Child (bonus) http://plnkr.co/edit/DsZUzoQz6P2BY7skhhWu 34
  33. PARENT/CHILD import {...} from "angular2/core"; import {ChildComponent} from "./child.component"; @Component({

    selector: "my-parent", template: `Parent <my-child></my-child> <ng-content></ng-content>`, directives: [ChildComponent] }) export class ParentComponent { @ViewChild(ChildComponent) child: ChildComponent; @ViewChildren(ChildComponent) children: QueryList<ChildComponent>; } parent.component.ts 35 <my-parent> <my-child></my-child> </my-parent> Template - app.component.ts
  34. PARENT/CHILD import {...} from "angular2/core"; import {ChildComponent} from "./child.component"; @Component({

    selector: "my-parent", template: `Parent <my-child></my-child> <ng-content></ng-content>`, directives: [ChildComponent] }) export class ParentComponent { @ViewChild(ChildComponent) child: ChildComponent; @ViewChildren(ChildComponent) children: QueryList<ChildComponent>; } parent.component.ts 36 <my-parent> <my-child></my-child> </my-parent> Template - app.component.ts
  35. PARENT/CHILD import {...} from "angular2/core"; import {ChildComponent} from "./child.component"; @Component({

    selector: "my-parent", template: `Parent <my-child></my-child> <ng-content></ng-content>`, directives: [ChildComponent] }) export class ParentComponent { @ViewChild(ChildComponent) child: ChildComponent; @ViewChildren(ChildComponent) children: QueryList<ChildComponent>; } parent.component.ts 37 <my-parent> <my-child></my-child> </my-parent> Template - app.component.ts
  36. PARENT/CHILD child.component.ts 38 import {...} from "angular2/core"; import {ParentComponent} from

    "./parent.component"; @Component({ selector: "my-child", template: "Child", }) export class ChildComponent { constructor(@Inject(forwardRef(() => ParentComponent)) parent: ParentComponent) {} }