angular 2 design patterns

30
Angular 2 Design Patterns

Upload: fitc

Post on 11-Apr-2017

3.177 views

Category:

Internet


0 download

TRANSCRIPT

Page 1: Angular 2 Design Patterns

Angular 2 Design Patterns

Page 2: Angular 2 Design Patterns

Component Communication

Page 3: Angular 2 Design Patterns

What is a component

Page 4: Angular 2 Design Patterns

@Component({ selector: 'myComp', template: `<div> Content: {{myVar}} </div>`})class MyComponent { myVar: string;

constructor() { this.myVar = 'hello'; }}

Output

Input<html> <myComp></myComp></html>

<html> <myComp> <div> Content: hello </div> </myComp></html>

Page 5: Angular 2 Design Patterns

Parent → Child

Page 6: Angular 2 Design Patterns

@Component({ selector: 'parent', template: `<div> Parent content <child [param]="myVar"></child> Parent content</div>`})class ParentComponent { myVar = 'hello';}

@Component({ selector: 'child', template: '<div>Child: {{param}}</div>'})class ChildComponent { @Input() param: string;}

<html> <parent> <div> Parent content <child> Child hello </child> Parent content </div> </parent></html>

Output

Input<html> <parent></parent></html>

Page 7: Angular 2 Design Patterns

@Input() Demo

Page 8: Angular 2 Design Patterns

Child → Parent

Page 9: Angular 2 Design Patterns

@Component({ selector: 'parent', template: `<div> <child (childEvent)="handelChildEvent($event)"></child></div>`})class ParentComponent { handelChildEvent(message) { console.log(message); }}

@Component({ selector: 'child', template: ` <button (click)="childEvent.emit('clicked')">Click me</button>`})class ChildComponent { @Output() childEvent = new EventEmitter();}

Page 10: Angular 2 Design Patterns

@Output() Demo

Page 11: Angular 2 Design Patterns

Sibling → Sibling

Page 12: Angular 2 Design Patterns

@Component({ selector: 'sibling2', template: `<button (click)="myService.increment()"> Increment</button>`})class Sibling2Component { constructor(public myService: MyService) {

}}

@Component({ selector: 'sibling1', template: `{{myService.counter}}`})class Sibling1Component { constructor(public myService: MyService) {

}}

class MyService { counter: number = 0;

increment() { this.counter++; }}

Page 13: Angular 2 Design Patterns

Sibling Demo

Page 14: Angular 2 Design Patterns

user.service.tsexport class UserService { users: User[] = [];}

Page 15: Angular 2 Design Patterns

user.service.tsexport class UserService { private users$ = new BehaviorSubject([]);}

Page 16: Angular 2 Design Patterns

user.service.tsexport class UserService { private users$ = new BehaviorSubject([]);

addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); }}

Page 17: Angular 2 Design Patterns

user.service.tsexport class UserService { private users$ = new BehaviorSubject([]);

addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); }

removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); }}

Page 18: Angular 2 Design Patterns

user.service.tsexport class UserService { private users$ = new BehaviorSubject([]);

addUser(user) { let users = [user, ...this.users$.getValue()]; this.users$.next(users); }

removeUser(user) { let users = this.users$.getValue().filter(u => u !== user); this.users$.next(users); }

getUsers() { return this.users$.asObservable(); }}

Page 19: Angular 2 Design Patterns

userSearch.component.ts@Component({ selector: 'user-search', template: `...<div *ngFor="let user of users | async"> ...</div>`})export class UserSearchComponent { users: Observable<User[]>;

constructor(public userService: UserService) { this.users = userService.getUsers(); }}

Page 20: Angular 2 Design Patterns

userSearch.component.ts@Component({ selector: 'user-search', template: `...First Name:<input #firstName (keyup)="firstNameSearch.next(firstName.value)">...`})export class UserSearchComponent { firstNameSearch = new BehaviorSubject('');}

Page 21: Angular 2 Design Patterns

userSearch.component.ts@Component({ selector: 'user-search', template: `...`})export class UserSearchComponent { users: Observable<User[]>; firstNameSearch = new BehaviorSubject('');

constructor(private userService: UserService) { this.users = Observable.combineLatest( userService.getUsers(), this.firstNameSearch, (users, search) => { return users.filter(user => user.firstName.includes(search)); } ); }}

Page 22: Angular 2 Design Patterns

userSearch.component.ts@Component({ selector: 'user-search', template: `...`})export class UserSearchComponent { users: Observable<User[]>;

constructor(private userService: UserService) { ... }

removeUser(user: User) { this.userService.removeUser(user); }}

Page 23: Angular 2 Design Patterns

Redux Demo

Page 24: Angular 2 Design Patterns

Takeaways

- Everything is a component!!!

Page 25: Angular 2 Design Patterns

Takeaways - Parent → Child

- Use an @Input() binding on child component

- Use es6 setters or ngOnChanges() to handle changes

- When @Input() doesn’t work, inject a @ViewChild()

Page 26: Angular 2 Design Patterns

Takeaways - Child → Parent

- Use an @Output() binding on child component

- Pass events to parent through an EventEmitter()@Output() doThing = new EventEmitter();doThing.emit('some event');

- In the parent, get the payload of the event with $event<child (doThing)="handelThing($event)"></child>

- If you can’t use an @Output() binding you can inject the parent component directly into the child

Page 27: Angular 2 Design Patterns

Takeaways - Sibling → Sibling

- Use a service to communicate between siblings

- Try to avoid sharing mutable state- Use observables to push events out

from a service to componentsprivate state$ = new BehaviorSubject<>({});doSomething(thing) { this.state$.next(thing);}

Page 28: Angular 2 Design Patterns

Takeaways - ngrx/store (Redux)

- ngrx/store library brings redux like approach to Angular 2

- Centralized state- One way data flow

Page 30: Angular 2 Design Patterns

Rob McDiarmidSlides: tinyurl.com/ng2-components

@robianmcd