Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

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.

Fabian Gosebrink

October 25, 2024
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. export class ContentComponent implements OnInit { private readonly service =

    inject(Service); items: Todo[]; doneItems: Todo[]; 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
  2. export class ContentComponent implements OnInit { private readonly service =

    inject(Service); items: Todo[]; doneItems: Todo[]; 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 doneItems: Todo[]; export class ContentComponent implements OnInit { 1 private readonly service = inject(Service); 2 3 items: Todo[]; 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
  3. export class ContentComponent implements OnInit { private readonly service =

    inject(Service); items: Todo[]; doneItems: Todo[]; 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 doneItems: Todo[]; export class ContentComponent implements OnInit { 1 private readonly service = inject(Service); 2 3 items: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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
  4. export class ContentComponent implements OnInit { private readonly service =

    inject(Service); items: Todo[]; doneItems: Todo[]; 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 doneItems: Todo[]; export class ContentComponent implements OnInit { 1 private readonly service = inject(Service); 2 3 items: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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
  5. export class ContentComponent implements OnInit { private readonly service =

    inject(Service); items: Todo[]; doneItems: Todo[]; 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 doneItems: Todo[]; export class ContentComponent implements OnInit { 1 private readonly service = inject(Service); 2 3 items: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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
  6. export class ContentComponent implements OnInit { private readonly service =

    inject(Service); items: Todo[]; doneItems: Todo[]; 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 doneItems: Todo[]; export class ContentComponent implements OnInit { 1 private readonly service = inject(Service); 2 3 items: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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 private readonly service = inject(Service); 2 3 items: Todo[]; 4 doneItems: Todo[]; 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
  7. <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
  8. <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
  9. export class TodoListComponent { items = input<Todo[]>([]) doneItems = input<Todo[]>([])

    markAsDone = output(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10
  10. export class TodoListComponent { items = input<Todo[]>([]) doneItems = input<Todo[]>([])

    markAsDone = output(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10 items = input<Todo[]>([]) doneItems = input<Todo[]>([]) export class TodoListComponent { 1 2 3 4 markAsDone = output(); 5 6 moveToDone(item: Todo) { 7 this.markAsDone.emit(item); 8 } 9 } 10
  11. export class TodoListComponent { items = input<Todo[]>([]) doneItems = input<Todo[]>([])

    markAsDone = output(); moveToDone(item: Todo) { this.markAsDone.emit(item); } } 1 2 3 4 5 6 7 8 9 10 items = input<Todo[]>([]) doneItems = input<Todo[]>([]) export class TodoListComponent { 1 2 3 4 markAsDone = output(); 5 6 moveToDone(item: Todo) { 7 this.markAsDone.emit(item); 8 } 9 } 10 markAsDone = output(); this.markAsDone.emit(item); export class TodoListComponent { 1 items = input<Todo[]>([]) 2 doneItems = input<Todo[]>([]) 3 4 5 6 moveToDone(item: Todo) { 7 8 } 9 } 10
  12. S I N G L E S O U R

    C E O F T R U T H
  13. S T O R E import { Component, OnInit }

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

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent { private readonly service = inject(Service); } 1 2 3 4 5 6 7 8 9 import { Store } from '@ngrx/store'; private readonly service = inject(Service); import { Component, OnInit } from '@angular/core'; 1 2 3 @Component({ /*...*/ }) 4 export class ContentComponent { 5 6 7 8 } 9
  15. S T A T E import { Component, OnInit }

    from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent { private readonly Store = inject(Store); items$ = this.store.select(state => state.items); loading$ = this.store.select(state => state.loading); } 1 2 3 4 5 6 7 8 9 10
  16. 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
  17. 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
  18. A C T I O N S export const TodoActions

    = createActionGroup({ ... }); 1 2 3
  19. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { // ... }, }); 1 2 3 4 5 6
  20. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  21. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 'Add Todo': props<{ value: string }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16
  22. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 'Add Todo': props<{ value: string }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Add Todo Finished': props<{ todo: Todo }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16
  23. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 'Add Todo': props<{ value: string }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Add Todo Finished': props<{ todo: Todo }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 7 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16
  24. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 'Add Todo': props<{ value: string }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Add Todo Finished': props<{ todo: Todo }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 7 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 10 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16
  25. A C T I O N S export const TodoActions

    = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 'Add Todo': props<{ value: string }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Add Todo Finished': props<{ todo: Todo }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 7 8 9 'Set As Done': props<{ todo: Todo }>(), 10 'Set As Done Finished': props<{ todo: Todo }>(), 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), export const TodoActions = createActionGroup({ 1 source: 'Todo', 2 events: { 3 'Add Todo': props<{ value: string }>(), 4 'Add Todo Finished': props<{ todo: Todo }>(), 5 6 'Load All Todos': emptyProps(), 7 'Load All Todos Finished': props<{ todos: Todo[] }>(), 8 9 10 11 12 'Delete Todo': props<{ todo: Todo }>(), 13 'Delete Todo Finished': props<{ todo: Todo }>(), 14 }, 15 }); 16 export const TodoActions = createActionGroup({ source: 'Todo', events: { 'Add Todo': props<{ value: string }>(), 'Add Todo Finished': props<{ todo: Todo }>(), 'Load All Todos': emptyProps(), 'Load All Todos Finished': props<{ todos: Todo[] }>(), 'Set As Done': props<{ todo: Todo }>(), 'Set As Done Finished': props<{ todo: Todo }>(), 'Delete Todo': props<{ todo: Todo }>(), 'Delete Todo Finished': props<{ todo: Todo }>(), }, }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
  26. A C T I O N S import { Component,

    OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { TodoActions } from './todo.actions'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { private readonly store = inject(Store); this.items$ = this.store.select(state => state...); ngOnInit() { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  27. R E D U C E R export interface TodoState

    { items: Todo[]; selectedItem: Todo; loading: boolean; } export const initialState: TodoState = { items: [], selectedItem: null, loading: false }; 1 2 3 4 5 6 7 8 9 10 11
  28. R E D U C E R export interface TodoState

    { ... } export const initialState: TodoState = { ... }; 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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 on(TodoActions.loadAllTodosFinished, (state, { payload }) => { return { ...state, loading: false, items: [...payload], }; }), const todoReducer = createReducer( 1 initialState, 2 on(TodoActions.loadAllTodos, 3 (state) => ({ 4 ...state, 5 loading: true, 6 }) 7 ), 8 9 10 11 12 13 14 15 16 17 ); 18
  38. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    private readonly store = inject(Store); items$ = this.store.pipe(select(/*...*/)); ngOnInit() { 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
  39. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    private readonly store = inject(Store); items$ = this.store.pipe(select(/*...*/)); ngOnInit() { 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 items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18
  40. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    private readonly store = inject(Store); items$ = this.store.pipe(select(/*...*/)); ngOnInit() { 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 items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18
  41. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    private readonly store = inject(Store); items$ = this.store.pipe(select(/*...*/)); ngOnInit() { 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 items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18
  42. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    private readonly store = inject(Store); items$ = this.store.pipe(select(/*...*/)); ngOnInit() { 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 items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.addTodo({ payload: item })); } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 12 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18
  43. @Component({/* ... */ }) export class ContentComponent implements OnInit {

    private readonly store = inject(Store); items$ = this.store.pipe(select(/*...*/)); ngOnInit() { 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 items$ = this.store.pipe(select(/*...*/)); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.loadAllTodos()); @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.addTodo({ payload: item })); } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 12 13 14 markAsDone(item: Todo) { 15 this.store.dispatch(TodoActions.setAsDone({ payload: item })); 16 } 17 } 18 this.store.dispatch(TodoActions.setAsDone({ payload: item })); } } @Component({/* ... */ }) 1 export class ContentComponent implements OnInit { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(/*...*/)); 5 6 ngOnInit() { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 10 addTodo(item: string) { 11 this.store.dispatch(TodoActions.addTodo({ payload: item })); 12 } 13 14 markAsDone(item: Todo) { 15 16 17 18
  44. <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
  45. export const appConfig = { providers: [ provideRouter(APP_ROUTES), provideHttpClient(), importProvidersFrom(

    StoreModule.forRoot({}), EffectsModule.forRoot([]) ), ], }; 1 2 3 4 5 6 7 8 9 10
  46. export const appConfig = { providers: [ provideRouter(APP_ROUTES), provideHttpClient(), importProvidersFrom(

    StoreModule.forRoot({}), EffectsModule.forRoot([]) ), ], }; 1 2 3 4 5 6 7 8 9 10 importProvidersFrom( StoreModule.forRoot({}), EffectsModule.forRoot([]) ), export const appConfig = { 1 providers: [ 2 provideRouter(APP_ROUTES), 3 provideHttpClient(), 4 5 6 7 8 ], 9 }; 10
  47. export const appConfig = { providers: [ provideRouter(APP_ROUTES), provideHttpClient(), importProvidersFrom(

    StoreModule.forRoot({}), EffectsModule.forRoot([]) ), ], }; 1 2 3 4 5 6 7 8 9 10 { } 1 2 3
  48. export const appConfig = { providers: [ provideRouter(APP_ROUTES), provideHttpClient(), importProvidersFrom(

    StoreModule.forRoot({}), EffectsModule.forRoot([]) ), ], }; 1 2 3 4 5 6 7 8 9 10 importProvidersFrom( StoreModule.forRoot({}), EffectsModule.forRoot([]) ), export const appConfig = { 1 providers: [ 2 provideRouter(APP_ROUTES), 3 provideHttpClient(), 4 5 6 7 8 ], 9 }; 10 { } 1 2 3
  49. export const TODO_ROUTES: Routes = [ { path: '', component:

    TodoMainComponent, providers: [ importProvidersFrom( StoreModule.forFeature("todo", todoReducer), EffectsModule.forFeature([TodoEffects]) ), ], }, ]; 1 2 3 4 5 6 7 8 9 10 11 12 { todo: { // ... } } 1 2 3 4 5
  50. export const TODO_ROUTES: Routes = [ { path: '', component:

    TodoMainComponent, providers: [ importProvidersFrom( StoreModule.forFeature("todo", todoReducer), EffectsModule.forFeature([TodoEffects]) ), ], }, ]; 1 2 3 4 5 6 7 8 9 10 11 12 { todo: { // ... } } 1 2 3 4 5
  51. { todo: { items: [], selectedItem: null, loading: false }

    } 1 2 3 4 5 6 7 export const TODO_ROUTES: Routes = [ { path: '', component: TodoMainComponent, providers: [ importProvidersFrom( StoreModule.forFeature("todo", todoReducer), EffectsModule.forFeature([TodoEffects]) ), ], }, ]; 1 2 3 4 5 6 7 8 9 10 11 12
  52. { todo: { items: [], selectedItem: null, loading: false }

    } 1 2 3 4 5 6 7 export const TODO_ROUTES: Routes = [ { path: '', component: TodoMainComponent, providers: [ importProvidersFrom( StoreModule.forFeature("todo", todoReducer), EffectsModule.forFeature([TodoEffects]) ), ], }, ]; 1 2 3 4 5 6 7 8 9 10 11 12
  53. SELECTORS import { Component, OnInit } from '@angular/core'; import {

    Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { private readonly store = inject(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
  54. 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 private readonly store = inject(Store); 6 7 ngOnInit() { 8 9 10 11 12 13 14 15 } 16 } 17
  55. 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 private readonly store = inject(Store); 6 7 ngOnInit() { 8 9 10 11 12 13 14 15 } 16 } 17
  56. 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 private readonly store = inject(Store); 6 7 ngOnInit() { 8 9 10 11 12 13 14 15 } 16 } 17
  57. 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 private readonly store = inject(Store); 6 7 ngOnInit() { 8 9 10 11 12 13 14 15 } 16 } 17 import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { private readonly store = inject(Store); ngOnInit() { const items$ = this.store.pipe( select((state) => state.todo.items.filter((x) => !x.done)) ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  58. SELECTORS import { Component, OnInit } from '@angular/core'; import {

    Store } from '@ngrx/store'; @Component({ /*...*/ }) export class ContentComponent implements OnInit { private readonly store = inject(Store); ngOnInit() { const items$ = this.store.pipe( select((state) => state.todo.items.filter((x) => !x.done)) ); const doneItems$ = this.store.pipe( select((state) => state.todo.items.filter((x) => x.done)) ); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
  59. 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
  60. 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
  61. 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
  62. 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
  63. 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
  64. SELECTORS export class ContentComponent implements OnInit { private readonly service

    = inject(Service); items: Todo[]; doneItems: Todo[]; 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
  65. SELECTORS export class ContentComponent implements OnInit { private readonly store

    = inject(Store); items$ = this.store.select(getAllUndoneItems); doneItems$ = this.store.select(getAllDoneItems); ngOnInit() { this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10
  66. SELECTORS export class ContentComponent implements OnInit { private readonly store

    = inject(Store); items$ = this.store.select(getAllUndoneItems); doneItems$ = this.store.select(getAllDoneItems); ngOnInit() { this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 items$ = this.store.select(getAllUndoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 4 doneItems$ = this.store.select(getAllDoneItems); 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10
  67. SELECTORS export class ContentComponent implements OnInit { private readonly store

    = inject(Store); items$ = this.store.select(getAllUndoneItems); doneItems$ = this.store.select(getAllDoneItems); ngOnInit() { this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 items$ = this.store.select(getAllUndoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 4 doneItems$ = this.store.select(getAllDoneItems); 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10 doneItems$ = this.store.select(getAllDoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 items$ = this.store.select(getAllUndoneItems); 4 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10
  68. SELECTORS export class ContentComponent implements OnInit { private readonly store

    = inject(Store); items$ = this.store.select(getAllUndoneItems); doneItems$ = this.store.select(getAllDoneItems); ngOnInit() { this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 items$ = this.store.select(getAllUndoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 4 doneItems$ = this.store.select(getAllDoneItems); 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10 doneItems$ = this.store.select(getAllDoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 items$ = this.store.select(getAllUndoneItems); 4 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10 this.store.dispatch(todoActions.loadAllTodos()); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 items$ = this.store.select(getAllUndoneItems); 4 doneItems$ = this.store.select(getAllDoneItems); 5 6 ngOnInit() { 7 8 } 9 } 10
  69. SELECTORS export class ContentComponent implements OnInit { private readonly store

    = inject(Store); items$ = this.store.select(getAllUndoneItems); doneItems$ = this.store.select(getAllDoneItems); ngOnInit() { this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 items$ = this.store.select(getAllUndoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 4 doneItems$ = this.store.select(getAllDoneItems); 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10 doneItems$ = this.store.select(getAllDoneItems); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 items$ = this.store.select(getAllUndoneItems); 4 5 6 ngOnInit() { 7 this.store.dispatch(todoActions.loadAllTodos()); 8 } 9 } 10 this.store.dispatch(todoActions.loadAllTodos()); export class ContentComponent implements OnInit { 1 private readonly store = inject(Store); 2 3 items$ = this.store.select(getAllUndoneItems); 4 doneItems$ = this.store.select(getAllDoneItems); 5 6 ngOnInit() { 7 8 } 9 } 10 export class ContentComponent implements OnInit { private readonly store = inject(Store); items$ = this.store.select(getAllUndoneItems); doneItems$ = this.store.select(getAllDoneItems); ngOnInit() { this.store.dispatch(todoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10