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

Angular Architectures with NgRx Stores & Effects

Angular Architectures with NgRx Stores & Effects

Angular offers many possibilities in the frontend, but also some challenges. If an application grows, sooner or later you have to deal with the issue of the state of the application. But what do "stateful" and "stateless" mean anyway? What are "Container Components" and "Presentation Components"? And how do I get a clean grip on the state of my application in the frontend? Tools like ngrx can help us to design our application cleanly and especially for large applications they help to keep track of the state. In this talk by Fabian Gosebrink, you will learn how these tools can be used and help you to manage even large applications with Angular.

Fb89953d3a1b1fcb862a186585c37c25?s=128

Fabian Gosebrink

April 26, 2022
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. ARCHITECTURES WITH STORES & EFFECTS

  2. Component Component Component Component Component

  3. Component Component Component REST Component Component

  4. REST Component Component Component Component Component

  5. None
  6. None
  7. O N E W A Y D A T A

    F L O W
  8. Component Component Component REST Component Component

  9. Component Component Component REST Component Component

  10. S T A T E F U L

  11. Component Component Component REST Component Component

  12. Component Component Component REST Component Component

  13. export class ContentComponent implements OnInit { items: Todo[]; doneItems: Todo[];

    constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe(data => this.items = data); this.service.detDoneItems() .subscribe(data => this.doneItems = data); } addTodo(item: string) { // ... } markAsDone(item: Todo) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  14. export class ContentComponent implements OnInit { items: Todo[]; doneItems: Todo[];

    constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe(data => this.items = data); this.service.detDoneItems() .subscribe(data => this.doneItems = data); } addTodo(item: string) { // ... } markAsDone(item: Todo) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 constructor(private service: Service) {} export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22
  15. export class ContentComponent implements OnInit { items: Todo[]; doneItems: Todo[];

    constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe(data => this.items = data); this.service.detDoneItems() .subscribe(data => this.doneItems = data); } addTodo(item: string) { // ... } markAsDone(item: Todo) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 constructor(private service: Service) {} export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.getData() .subscribe(data => this.items = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 8 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22
  16. export class ContentComponent implements OnInit { items: Todo[]; doneItems: Todo[];

    constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe(data => this.items = data); this.service.detDoneItems() .subscribe(data => this.doneItems = data); } addTodo(item: string) { // ... } markAsDone(item: Todo) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 constructor(private service: Service) {} export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.getData() .subscribe(data => this.items = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 8 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.detDoneItems() .subscribe(data => this.doneItems = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 11 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22
  17. export class ContentComponent implements OnInit { items: Todo[]; doneItems: Todo[];

    constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe(data => this.items = data); this.service.detDoneItems() .subscribe(data => this.doneItems = data); } addTodo(item: string) { // ... } markAsDone(item: Todo) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 constructor(private service: Service) {} export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.getData() .subscribe(data => this.items = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 8 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.detDoneItems() .subscribe(data => this.doneItems = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 11 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 addTodo(item: string) { // ... } export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 15 16 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22
  18. export class ContentComponent implements OnInit { items: Todo[]; doneItems: Todo[];

    constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe(data => this.items = data); this.service.detDoneItems() .subscribe(data => this.doneItems = data); } addTodo(item: string) { // ... } markAsDone(item: Todo) { // ... } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 constructor(private service: Service) {} export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.getData() .subscribe(data => this.items = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 8 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 this.service.detDoneItems() .subscribe(data => this.doneItems = data); export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 11 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 addTodo(item: string) { // ... } export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 15 16 17 18 markAsDone(item: Todo) { 19 // ... 20 } 21 } 22 markAsDone(item: Todo) { // ... } export class ContentComponent implements OnInit { 1 items: Todo[]; 2 doneItems: Todo[]; 3 4 constructor(private service: Service) {} 5 6 ngOnInit() { 7 this.service.getData() 8 .subscribe(data => this.items = data); 9 10 this.service.detDoneItems() 11 .subscribe(data => this.doneItems = data); 12 } 13 14 addTodo(item: string) { 15 // ... 16 } 17 18 19 20 21 } 22
  19. <div> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list [items]="items" [doneItems]="doneItems" (markAsDone)="markAsDone($event)" ></app-todo-list> </div>

    1 2 3 4 5 6 7 8 9 10 11
  20. <div> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list [items]="items" [doneItems]="doneItems" (markAsDone)="markAsDone($event)" ></app-todo-list> </div>

    1 2 3 4 5 6 7 8 9 10 11 <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <div> 1 2 3 4 5 <app-todo-list 6 [items]="items" 7 [doneItems]="doneItems" 8 (markAsDone)="markAsDone($event)" 9 ></app-todo-list> 10 </div> 11
  21. <div> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list [items]="items" [doneItems]="doneItems" (markAsDone)="markAsDone($event)" ></app-todo-list> </div>

    1 2 3 4 5 6 7 8 9 10 11 <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <div> 1 2 3 4 5 <app-todo-list 6 [items]="items" 7 [doneItems]="doneItems" 8 (markAsDone)="markAsDone($event)" 9 ></app-todo-list> 10 </div> 11 <app-todo-list [items]="items" [doneItems]="doneItems" (markAsDone)="markAsDone($event)" ></app-todo-list> <div> 1 <app-todo-form 2 (todoAdded)="addTodo($event)"> 3 </app-todo-form> 4 5 6 7 8 9 10 </div> 11
  22. Component Component Component REST Component Component

  23. S T A T E L E S S

  24. Component Component Component REST Component Component

  25. export class TodoListComponent { @Input() items: Todo[] = []; @Input()

    doneItems: Todo[] = []; @Output() markAsDone = new EventEmitter(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10
  26. export class TodoListComponent { @Input() items: Todo[] = []; @Input()

    doneItems: Todo[] = []; @Output() markAsDone = new EventEmitter(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10 @Input() items: Todo[] = []; @Input() doneItems: Todo[] = []; export class TodoListComponent { 1 2 3 4 @Output() markAsDone = new EventEmitter(); 5 6 moveToDone(item: Todo) { 7 this.markAsDone.emit(item); 8 } 9 } 10
  27. export class TodoListComponent { @Input() items: Todo[] = []; @Input()

    doneItems: Todo[] = []; @Output() markAsDone = new EventEmitter(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10 @Input() items: Todo[] = []; @Input() doneItems: Todo[] = []; export class TodoListComponent { 1 2 3 4 @Output() markAsDone = new EventEmitter(); 5 6 moveToDone(item: Todo) { 7 this.markAsDone.emit(item); 8 } 9 } 10 @Output() markAsDone = new EventEmitter(); this.markAsDone.emit(item); export class TodoListComponent { 1 @Input() items: Todo[] = []; 2 @Input() doneItems: Todo[] = []; 3 4 5 6 moveToDone(item: Todo) { 7 8 } 9 } 10
  28. export class TodoListComponent { @Input() items: Todo[] = []; @Input()

    doneItems: Todo[] = []; @Output() markAsDone = new EventEmitter(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10 @Input() items: Todo[] = []; @Input() doneItems: Todo[] = []; export class TodoListComponent { 1 2 3 4 @Output() markAsDone = new EventEmitter(); 5 6 moveToDone(item: Todo) { 7 this.markAsDone.emit(item); 8 } 9 } 10 @Output() markAsDone = new EventEmitter(); this.markAsDone.emit(item); export class TodoListComponent { 1 @Input() items: Todo[] = []; 2 @Input() doneItems: Todo[] = []; 3 4 5 6 moveToDone(item: Todo) { 7 8 } 9 } 10 export class TodoListComponent { @Input() items: Todo[] = []; @Input() doneItems: Todo[] = []; @Output() markAsDone = new EventEmitter(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10
  29. Component Component Component REST Component Component

  30. Component Component Component REST Component Component MULTIPLE TIMES

  31. S I N G L E S O U R

    C E O F T R U T H
  32. S T A T E

  33. ARCHITECTURES WITH STORES & EFFECTS

  34. Component REST Service

  35. Component REST State ...

  36. S T O R E

  37. S T O R E V S S T A

    T E
  38. S T O R E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent { constructor(private store: Store) {} } 1 2 3 4 5 6 7 8 9
  39. S T O R E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent { constructor(private store: Store) {} } 1 2 3 4 5 6 7 8 9 import { Store } from '@ngrx/store'; constructor(private store: Store) {} import { Component, OnInit } from '@angular/core'; 1 2 3 @Component({ /*...*/ }) 4 export class ContentComponent { 5 6 7 8 } 9
  40. Component Store

  41. S T A T E

  42. S T A T E

  43. S T A T E

  44. S T A T E

  45. S T A T E

  46. S T A T E

  47. Component Store State

  48. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  49. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 constructor(private store: Store) {} import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15
  50. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 constructor(private store: Store) {} import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.items$ = this.store.select(state => state.items); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15
  51. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 constructor(private store: Store) {} import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.items$ = this.store.select(state => state.items); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.loading$ = this.store.select(state => state.loading); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 13 } 14 } 15
  52. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 constructor(private store: Store) {} import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.items$ = this.store.select(state => state.items); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.loading$ = this.store.select(state => state.loading); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 13 } 14 } 15 items$: Observable<Todo[]>; loading$: Observable<boolean>; import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15
  53. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 constructor(private store: Store) {} import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.items$ = this.store.select(state => state.items); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 this.loading$ = this.store.select(state => state.loading); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 items$: Observable<Todo[]>; 6 loading$: Observable<boolean>; 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 13 } 14 } 15 items$: Observable<Todo[]>; loading$: Observable<boolean>; import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 7 8 constructor(private store: Store) {} 9 10 ngOnInit() { 11 this.items$ = this.store.select(state => state.items); 12 this.loading$ = this.store.select(state => state.loading); 13 } 14 } 15 import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { items$: Observable<Todo[]>; loading$: Observable<boolean>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state.items); this.loading$ = this.store.select(state => state.loading); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  54. S T A T E <div> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list

    [items]="items$ | async" ... (markAsDone)="markAsDone($event)" ></app-todo-list> </div> 1 2 3 4 5 6 7 8 9 10 11
  55. S T A T E <div> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list

    [items]="items$ | async" ... (markAsDone)="markAsDone($event)" ></app-todo-list> </div> 1 2 3 4 5 6 7 8 9 10 11 [items]="items$ | async" <div> 1 <app-todo-form 2 (todoAdded)="addTodo($event)"> 3 </app-todo-form> 4 5 <app-todo-list 6 7 ... 8 (markAsDone)="markAsDone($event)" 9 ></app-todo-list> 10 </div> 11
  56. STATE MANIPULATION?

  57. A C T I O N S

  58. A C T I O N S import { createAction

    } from '@ngrx/store'; createAction(...); 1 2 3
  59. A C T I O N S import { createAction

    } from '@ngrx/store'; createAction('[Todo] Load Todos'); 1 2 3
  60. A C T I O N S import { createAction

    } from '@ngrx/store'; export const loadAllTodos = createAction('[Todo] Load Todos'); 1 2 3
  61. A C T I O N S import { createAction

    } from '@ngrx/store'; export const loadAllTodos = createAction('[Todo] Load Todos'); export const loadAllTodosFinished = createAction( '[Todo] Load Todos Finished' ); 1 2 3 4 5 6 7
  62. A C T I O N S import { createAction,

    props } from '@ngrx/store'; export const loadAllTodos = createAction('[Todo] Load Todos'); export const loadAllTodosFinished = createAction( '[Todo] Load Todos Finished', props<{ payload: Todo[] }>() ); 1 2 3 4 5 6 7 8
  63. A C T I O N S import { createAction,

    props } from '@ngrx/store'; export const loadAllTodos = createAction('[Todo] Load Todos'); export const loadAllTodosFinished = createAction( '[Todo] Load Todos Finished', props<{ payload: Todo[] }>() ); export const addTodo = createAction( '[Todo] Add Todo', props<{ payload: string }>() ); export const addTodoFinished = createAction( '[Todo] Add Todo Finished', props<{ payload: Todo }>() ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  64. A C T I O N S import { Component,

    OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import * as todoActions from '../../store/todo.actions'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state...); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  65. A C T I O N S import { Component,

    OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import * as todoActions from '../../store/todo.actions'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state...); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import * as todoActions from '../../store/todo.actions'; import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 4 @Component({ /*...*/ }) 5 export class ContentComponent implements OnInit { 6 7 constructor(private store: Store) {} 8 9 ngOnInit() { 10 this.items$ = this.store.select(state => state...); 11 12 this.store.dispatch(todoActions.loadAllTodos()); 13 } 14 } 15
  66. A C T I O N S import { Component,

    OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import * as todoActions from '../../store/todo.actions'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.select(state => state...); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import * as todoActions from '../../store/todo.actions'; import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 4 @Component({ /*...*/ }) 5 export class ContentComponent implements OnInit { 6 7 constructor(private store: Store) {} 8 9 ngOnInit() { 10 this.items$ = this.store.select(state => state...); 11 12 this.store.dispatch(todoActions.loadAllTodos()); 13 } 14 } 15 this.store.dispatch(todoActions.loadAllTodos()); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 import * as todoActions from '../../store/todo.actions'; 3 4 @Component({ /*...*/ }) 5 export class ContentComponent implements OnInit { 6 7 constructor(private store: Store) {} 8 9 ngOnInit() { 10 this.items$ = this.store.select(state => state...); 11 12 13 } 14 } 15
  67. R E D U C E R (oldState, action) =>

    newState 1
  68. R E D U C E R import { Action,

    createReducer, on } from '@ngrx/store'; import * as todoActions from './todo.actions'; export interface ReducerTodoState { items: Todo[]; selectedItem: Todo; loading: boolean; } export const initialState: ReducerTodoState = { items: [], selectedItem: null, loading: false }; 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  69. R E D U C E R import { Action,

    createReducer, on } from '@ngrx/store'; import * as todoActions from './todo.actions'; export interface ReducerTodoState { ... } export const initialState: ReducerTodoState = { ... }; const todoReducer = createReducer( initialState, on(todoActions.loadAllTodos, (state) => ({ ...state, loading: true, }) ), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  70. R E D U C E R import { Action,

    createReducer, on } from '@ngrx/store'; import * as todoActions from './todo.actions'; export interface ReducerTodoState { ... } export const initialState: ReducerTodoState = { ... }; const todoReducer = createReducer( initialState, on(todoActions.loadAllTodos, (state) => ({ ...state, loading: true, }) ), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const initialState: ReducerTodoState = { ... }; const todoReducer = createReducer( initialState, import { Action, createReducer, on } from '@ngrx/store'; 1 import * as todoActions from './todo.actions'; 2 3 export interface ReducerTodoState { ... } 4 5 6 7 8 9 on(todoActions.loadAllTodos, 10 (state) => ({ 11 ...state, 12 loading: true, 13 }) 14 ), 15 ); 16
  71. R E D U C E R import { Action,

    createReducer, on } from '@ngrx/store'; import * as todoActions from './todo.actions'; export interface ReducerTodoState { ... } export const initialState: ReducerTodoState = { ... }; const todoReducer = createReducer( initialState, on(todoActions.loadAllTodos, (state) => ({ ...state, loading: true, }) ), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const initialState: ReducerTodoState = { ... }; const todoReducer = createReducer( initialState, import { Action, createReducer, on } from '@ngrx/store'; 1 import * as todoActions from './todo.actions'; 2 3 export interface ReducerTodoState { ... } 4 5 6 7 8 9 on(todoActions.loadAllTodos, 10 (state) => ({ 11 ...state, 12 loading: true, 13 }) 14 ), 15 ); 16 on(todoActions.loadAllTodos, (state) => ({ ...state, loading: true, }) ), import { Action, createReducer, on } from '@ngrx/store'; 1 import * as todoActions from './todo.actions'; 2 3 export interface ReducerTodoState { ... } 4 5 export const initialState: ReducerTodoState = { ... }; 6 7 const todoReducer = createReducer( 8 initialState, 9 10 11 12 13 14 15 ); 16
  72. Component Store State Reducer Actions

  73. Component Store State Reducer Actions

  74. Component Store State Reducer Actions

  75. Component Store State Reducer Actions

  76. Component Store State Reducer Actions

  77. Component Store State Reducer Actions

  78. CONTAINER store.select(...) store.dispatch(…)

  79. CONTAINER store.select(...) store.dispatch(…) PRESENTATIONAL @Input(…) @Output(…)

  80. S Y N C

  81. S Y N C V S A S Y N

    C
  82. E F F E C T S @Injectable() export class

    TodoEffects { } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  83. E F F E C T S @Injectable() export class

    TodoEffects { loadTodos$ = createEffect(() => ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  84. E F F E C T S @Injectable() export class

    TodoEffects { loadTodos$ = createEffect(() => this.actions$.pipe( ) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  85. E F F E C T S @Injectable() export class

    TodoEffects { loadTodos$ = createEffect(() => this.actions$.pipe( ofType(todoActions.loadAllTodos), switchMap(() => ) ) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  86. E F F E C T S @Injectable() export class

    TodoEffects { loadTodos$ = createEffect(() => this.actions$.pipe( ofType(todoActions.loadAllTodos), switchMap(() => this.todoService .getItems() ) ) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  87. E F F E C T S @Injectable() export class

    TodoEffects { loadTodos$ = createEffect(() => this.actions$.pipe( ofType(todoActions.loadAllTodos), switchMap(() => this.todoService .getItems() .pipe( map((todos) => todoActions.loadAllTodosFinished({ payload: todos })) ) ) ) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  88. E F F E C T S @Injectable() export class

    TodoEffects { loadTodos$ = createEffect(() => this.actions$.pipe( ofType(todoActions.loadAllTodos), switchMap(() => this.todoService .getItems() .pipe( map((todos) => todoActions.loadAllTodosFinished({ payload: todos })) ) ) ) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 todoActions.loadAllTodosFinished({ payload: todos })) @Injectable() 1 export class TodoEffects { 2 loadTodos$ = createEffect(() => 3 this.actions$.pipe( 4 ofType(todoActions.loadAllTodos), 5 switchMap(() => 6 this.todoService 7 .getItems() 8 .pipe( 9 map((todos) => 10 11 ) 12 ) 13 ) 14 ); 15 } 16
  89. import { Action, createReducer, on } from '@ngrx/store'; import *

    as todoActions from './todo.actions'; const todoReducer = createReducer( initialState, on(todoActions.loadAllTodos, (state) => ({ ...state, loading: true, }) ), on(todoActions.loadAllTodosFinished, (state, { payload }) => { return { ...state, loading: false, items: [...payload], }; }), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
  90. import { Action, createReducer, on } from '@ngrx/store'; import *

    as todoActions from './todo.actions'; const todoReducer = createReducer( initialState, on(todoActions.loadAllTodos, (state) => ({ ...state, loading: true, }) ), on(todoActions.loadAllTodosFinished, (state, { payload }) => { return { ...state, loading: false, items: [...payload], }; }), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 on(todoActions.loadAllTodosFinished, (state, { payload }) => { return { ...state, loading: false, items: [...payload], }; }), import { Action, createReducer, on } from '@ngrx/store'; 1 import * as todoActions from './todo.actions'; 2 3 const todoReducer = createReducer( 4 initialState, 5 on(todoActions.loadAllTodos, 6 (state) => ({ 7 ...state, 8 loading: true, 9 }) 10 ), 11 12 13 14 15 16 17 18 19 ); 20
  91. Component Store State Reducer Actions

  92. Component Store State Reducer Effects Actions

  93. None
  94. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    items$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(/*...*/)); this.store.dispatch(todoActions.loadAllTodos()); } addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  95. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    items$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(/*...*/)); this.store.dispatch(todoActions.loadAllTodos()); } addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 constructor(private store: Store) {} @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19
  96. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    items$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(/*...*/)); this.store.dispatch(todoActions.loadAllTodos()); } addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 constructor(private store: Store) {} @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19
  97. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    items$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(/*...*/)); this.store.dispatch(todoActions.loadAllTodos()); } addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 constructor(private store: Store) {} @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.store.dispatch(todoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19
  98. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    items$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(/*...*/)); this.store.dispatch(todoActions.loadAllTodos()); } addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 constructor(private store: Store) {} @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.store.dispatch(todoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 12 13 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19
  99. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    items$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(/*...*/)); this.store.dispatch(todoActions.loadAllTodos()); } addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 constructor(private store: Store) {} @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 this.store.dispatch(todoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 addTodo(item: string) { this.store.dispatch(todoActions.addTodo({ payload: item })); } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 12 13 14 15 markAsDone(item: Todo) { 16 this.store.dispatch(todoActions.setAsDone({ payload: item })); 17 } 18 } 19 markAsDone(item: Todo) { this.store.dispatch(todoActions.setAsDone({ payload: item })); } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 items$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(/*...*/)); 8 this.store.dispatch(todoActions.loadAllTodos()); 9 } 10 11 addTodo(item: string) { 12 this.store.dispatch(todoActions.addTodo({ payload: item })); 13 } 14 15 16 17 18 } 19
  100. <h1>Todo App</h1> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list [items]="items$ | async" (markAsDone)="markAsDone($event)"

    ></app-todo-list> 1 2 3 4 5 6 7 8 9
  101. <h1>Todo App</h1> <app-todo-form (todoAdded)="addTodo($event)"> </app-todo-form> <app-todo-list [items]="items$ | async" (markAsDone)="markAsDone($event)"

    ></app-todo-list> 1 2 3 4 5 6 7 8 9 [items]="items$ | async" <h1>Todo App</h1> 1 2 <app-todo-form (todoAdded)="addTodo($event)"> 3 </app-todo-form> 4 5 <app-todo-list 6 7 (markAsDone)="markAsDone($event)" 8 ></app-todo-list> 9
  102. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forRoot({})

    ] }) export class AppModule {} 1 2 3 4 5 6 7 8
  103. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forRoot({})

    ] }) export class AppModule {} 1 2 3 4 5 6 7 8 { } 1 2 3
  104. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature(...)

    ] }) export class TodoModule {} 1 2 3 4 5 6 7 8
  105. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8
  106. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 StoreModule.forFeature("todo", todoReducer) import { StoreModule } from '@ngrx/store'; 1 2 @NgModule({ 3 imports: [ 4 5 ] 6 }) 7 export class TodoModule {} 8
  107. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 { todo: { // ... } } 1 2 3 4 5
  108. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 { todo: { // ... } } 1 2 3 4 5
  109. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 { todo: { items: [], selectedItem: null, loading: false } } 1 2 3 4 5 6 7
  110. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 { todo: { items: [], selectedItem: null, loading: false } } 1 2 3 4 5 6 7
  111. import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo",

    todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 import { StoreModule } from '@ngrx/store'; @NgModule({ imports: [ StoreModule.forFeature("todo", todoReducer) ] }) export class TodoModule {} 1 2 3 4 5 6 7 8 { todo: { items: [], selectedItem: null, loading: false } } 1 2 3 4 5 6 7
  112. SELECTORS import { Component, OnInit } from '@angular/core'; import {

    Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { constructor(private store: Store) {} ngOnInit() { const items$ = this.store.pipe( select((state) => state ) ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  113. SELECTORS import { Component, OnInit } from '@angular/core'; import {

    Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { constructor(private store: Store) {} ngOnInit() { const items$ = this.store.pipe( select((state) => state ) ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const items$ = this.store.pipe( select((state) => state ) ); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 constructor(private store: Store) {} 7 8 ngOnInit() { 9 10 11 12 13 14 15 16 } 17 } 18
  114. SELECTORS const items$ = this.store.pipe( select((state) => state.todo )) );

    import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 constructor(private store: Store) {} 7 8 ngOnInit() { 9 10 11 12 13 14 15 16 } 17 } 18
  115. SELECTORS const items$ = this.store.pipe( select((state) => state.todo.items )) );

    import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 constructor(private store: Store) {} 7 8 ngOnInit() { 9 10 11 12 13 14 15 16 } 17 } 18
  116. SELECTORS const items$ = this.store.pipe( select((state) => state.todo.items.filter((x) => !x.done))

    ); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 constructor(private store: Store) {} 7 8 ngOnInit() { 9 10 11 12 13 14 15 16 } 17 } 18
  117. SELECTORS const doneItems$ = this.store.pipe( select((state) => state.todo.items.filter((x) => x.done))

    ); import { Component, OnInit } from '@angular/core'; 1 import { Store } from '@ngrx/store'; 2 3 @Component({ /*...*/ }) 4 export class ContentComponent implements OnInit { 5 6 constructor(private store: Store) {} 7 8 ngOnInit() { 9 const items$ = this.store.pipe( 10 select((state) => state.todo.items.filter((x) => !x.done)) 11 ); 12 13 14 15 16 } 17 } 18
  118. SELECTORS export const getTodoState = createFeatureSelector<TodoState>("todo"); export const getAllUndoneItems =

    createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getSelectedItem = createSelector( getTodoState, (state: TodoState) => state.selectedItem ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  119. SELECTORS export const getTodoState = createFeatureSelector<TodoState>("todo"); export const getAllUndoneItems =

    createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getSelectedItem = createSelector( getTodoState, (state: TodoState) => state.selectedItem ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16
  120. SELECTORS export const getTodoState = createFeatureSelector<TodoState>("todo"); export const getAllUndoneItems =

    createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getSelectedItem = createSelector( getTodoState, (state: TodoState) => state.selectedItem ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16 export const getAllUndoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 3 4 5 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16
  121. SELECTORS export const getTodoState = createFeatureSelector<TodoState>("todo"); export const getAllUndoneItems =

    createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getSelectedItem = createSelector( getTodoState, (state: TodoState) => state.selectedItem ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16 export const getAllUndoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 3 4 5 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16 export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 8 9 10 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16
  122. SELECTORS export const getTodoState = createFeatureSelector<TodoState>("todo"); export const getAllUndoneItems =

    createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getSelectedItem = createSelector( getTodoState, (state: TodoState) => state.selectedItem ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16 export const getAllUndoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => !x.done) ); export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 3 4 5 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16 export const getAllDoneItems = createSelector( getTodoState, (state: TodoState) => state.items.filter((x) => x.done) ); export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 8 9 10 11 12 export const getSelectedItem = createSelector( 13 getTodoState, 14 (state: TodoState) => state.selectedItem 15 ); 16 export const getSelectedItem = createSelector( getTodoState, (state: TodoState) => state.selectedItem ); export const getTodoState = createFeatureSelector<TodoState>("todo"); 1 2 export const getAllUndoneItems = createSelector( 3 getTodoState, 4 (state: TodoState) => state.items.filter((x) => !x.done) 5 ); 6 7 export const getAllDoneItems = createSelector( 8 getTodoState, 9 (state: TodoState) => state.items.filter((x) => x.done) 10 ); 11 12 13 14 15 16
  123. SELECTORS export class ContentComponent implements OnInit { items: Todo[]; doneItems:

    Todo[]; constructor(private service: Service) {} ngOnInit() { this.service.getData() .subscribe((data) => { this.items = data }); this.service.detDoneItems() .subscribe((data) => { this.items = data }); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  124. SELECTORS export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$:

    Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13
  125. SELECTORS export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$:

    Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 constructor(private store: Store) {} export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13
  126. SELECTORS export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$:

    Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 constructor(private store: Store) {} export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.items$ = this.store.pipe(select(getAllUndoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13
  127. SELECTORS export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$:

    Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 constructor(private store: Store) {} export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.items$ = this.store.pipe(select(getAllUndoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13
  128. SELECTORS export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$:

    Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 constructor(private store: Store) {} export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.items$ = this.store.pipe(select(getAllUndoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.store.dispatch(todoActions.loadAllTodos()); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 11 } 12 } 13
  129. SELECTORS export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$:

    Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 constructor(private store: Store) {} export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.items$ = this.store.pipe(select(getAllUndoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 9 10 this.store.dispatch(todoActions.loadAllTodos()); 11 } 12 } 13 this.store.dispatch(todoActions.loadAllTodos()); export class ContentComponent implements OnInit { 1 items$: Observable<Todo[]>; 2 doneItems$: Observable<Todo[]>; 3 4 constructor(private store: Store) {} 5 6 ngOnInit() { 7 this.items$ = this.store.pipe(select(getAllUndoneItems)); 8 this.doneItems$ = this.store.pipe(select(getAllDoneItems)); 9 10 11 } 12 } 13 export class ContentComponent implements OnInit { items$: Observable<Todo[]>; doneItems$: Observable<Todo[]>; constructor(private store: Store) {} ngOnInit() { this.items$ = this.store.pipe(select(getAllUndoneItems)); this.doneItems$ = this.store.pipe(select(getAllDoneItems)); this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13
  130. @NGRX/DATA

  131. @NGRX/DATA import { EntityMetadataMap } from '@ngrx/data'; const entityMetadata: EntityMetadataMap

    = { Hero: {}, }; export const entityConfig = { entityMetadata }; 1 2 3 4 5 6 7 8 9
  132. @NGRX/DATA import ... import { EntityDataModule } from '@ngrx/data'; import

    { entityConfig } from './entity-metadata'; @NgModule({ imports: [ HttpClientModule, StoreModule.forRoot({}), EffectsModule.forRoot([]), EntityDataModule.forRoot(entityConfig) ] }) export class AppModule {} 1 2 3 4 5 6 7 8 9 10 11 12 13
  133. @NGRX/DATA import { Injectable } from '@angular/core'; import { EntityCollectionServiceBase,

    EntityCollectionServiceElementsFactory } from '@ngrx/data'; import { Hero } from '../core'; @Injectable({ providedIn: 'root' }) export class HeroService extends EntityCollectionServiceBase<Hero> { constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) { super('Hero', serviceElementsFactory); } } 1 2 3 4 5 6 7 8 9 10 11 12 13
  134. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
  135. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 5 6 7 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23
  136. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 5 6 7 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 loading$: Observable<boolean>; heroes$: Observable<Hero[]>; export class HeroesComponent implements OnInit { 1 2 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23
  137. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 5 6 7 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 loading$: Observable<boolean>; heroes$: Observable<Hero[]>; export class HeroesComponent implements OnInit { 1 2 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 add(hero: Hero) { this.heroService.add(hero); } 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 14 15 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 this.heroService.getAll(); 23 } 24 25 update(hero: Hero) { 26
  138. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 5 6 7 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 loading$: Observable<boolean>; heroes$: Observable<Hero[]>; export class HeroesComponent implements OnInit { 1 2 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 add(hero: Hero) { this.heroService.add(hero); } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 14 15 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 delete(hero: Hero) { this.heroService.delete(hero.id); } this.loading$ heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 18 19 20 21 getHeroes() { 22 this.heroService.getAll(); 23 } 24 25 update(hero: Hero) { 26 this.heroService.update(hero); 27 } 28 } 29
  139. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 5 6 7 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 loading$: Observable<boolean>; heroes$: Observable<Hero[]>; export class HeroesComponent implements OnInit { 1 2 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 add(hero: Hero) { this.heroService.add(hero); } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 14 15 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 delete(hero: Hero) { this.heroService.delete(hero.id); } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 18 19 20 21 getHeroes() { 22 hi h i ll 23 getHeroes() { this.heroService.getAll(); } this.loading$ heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 22 23 24 25 update(hero: Hero) { 26 this.heroService.update(hero); 27 } 28 } 29
  140. @NGRX/DATA export class HeroesComponent implements OnInit { loading$: Observable<boolean>; heroes$:

    Observable<Hero[]>; constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } ngOnInit() { this.getHeroes(); } add(hero: Hero) { this.heroService.add(hero); } delete(hero: Hero) { this.heroService.delete(hero.id); } getHeroes() { hi h i ll 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 constructor(private heroService: HeroService) { this.heroes$ = heroService.entities$; this.loading$ = heroService.loading$; } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 5 6 7 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 loading$: Observable<boolean>; heroes$: Observable<Hero[]>; export class HeroesComponent implements OnInit { 1 2 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 add(hero: Hero) { this.heroService.add(hero); } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 14 15 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 hi h i ll 23 delete(hero: Hero) { this.heroService.delete(hero.id); } export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 18 19 20 21 getHeroes() { 22 hi h i ll 23 getHeroes() { hi h i ll export class HeroesComponent implements OnInit { 1 loading$: Observable<boolean>; 2 heroes$: Observable<Hero[]>; 3 4 constructor(private heroService: HeroService) { 5 this.heroes$ = heroService.entities$; 6 this.loading$ = heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 22 23 update(hero: Hero) { this.heroService.update(hero); } this.loading$ heroService.loading$; 7 } 8 9 ngOnInit() { 10 this.getHeroes(); 11 } 12 13 add(hero: Hero) { 14 this.heroService.add(hero); 15 } 16 17 delete(hero: Hero) { 18 this.heroService.delete(hero.id); 19 } 20 21 getHeroes() { 22 this.heroService.getAll(); 23 } 24 25 26 27 28 } 29
  141. ARCHITECTURES WITH STORES & EFFECTS

  142. FABIAN GOSEBRINK

  143. TAKE CARE