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

Kickstarting Your Journey with NgRx Signal Store

Kickstarting Your Journey with NgRx Signal Store

Signals are making their way into Angular and with them a new kind of state management with the NgRx Signal Store. A new state management, based on Signals, offers a lean, declarative and reactive approach to state management. In this presentation, Fabian Gosebrink explains how and when the new NgRx Signal Store can be used, how it works and what advantages it brings. After the presentation, state management in your application should no longer be a problem.

Fabian Gosebrink

July 01, 2024
Tweet

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items$ = this.store.pipe(select(getAllItems)); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10
  2. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items$ = this.store.pipe(select(getAllItems)); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 private readonly store = inject(Store); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 3 4 items$ = this.store.pipe(select(getAllItems)); 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10
  3. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items$ = this.store.pipe(select(getAllItems)); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 private readonly store = inject(Store); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 3 4 items$ = this.store.pipe(select(getAllItems)); 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10 items$ = this.store.pipe(select(getAllItems)); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10
  4. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items$ = this.store.pipe(select(getAllItems)); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 private readonly store = inject(Store); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 3 4 items$ = this.store.pipe(select(getAllItems)); 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10 items$ = this.store.pipe(select(getAllItems)); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10 this.store.dispatch(TodoActions.loadAllTodos()); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 private readonly store = inject(Store); 3 4 items$ = this.store.pipe(select(getAllItems)); 5 6 ngOnInit(): void { 7 8 } 9 } 10
  5. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items$ = this.store.pipe(select(getAllItems)); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 <app-todo-list [items]="items$ | async" ></app-todo-list> 1 2 3
  6. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items$ = this.store.pipe(select(getAllItems)); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 items$ = this.store.pipe(select(getAllItems)); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10 <app-todo-list [items]="items$ | async" ></app-todo-list> 1 2 3
  7. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items = this.store.selectSignal(getAllItems); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 <app-todo-list [items]="items()" ></app-todo-list> 1 2 3
  8. @Component({ /* ... */ }) export class TodoMainComponent { private

    readonly store = inject(Store); items = this.store.selectSignal(getAllItems); ngOnInit(): void { this.store.dispatch(TodoActions.loadAllTodos()); } } 1 2 3 4 5 6 7 8 9 10 items = this.store.selectSignal(getAllItems); @Component({ /* ... */ }) 1 export class TodoMainComponent { 2 private readonly store = inject(Store); 3 4 5 6 ngOnInit(): void { 7 this.store.dispatch(TodoActions.loadAllTodos()); 8 } 9 } 10 <app-todo-list [items]="items()" ></app-todo-list> 1 2 3
  9. export interface TodoState { items: Todo[]; loading: boolean; } export

    const initialState: TodoState = { items: [], loading: false, }; export const TodoStore = signalStore( withState(initialState), ); 1 2 3 4 5 6 7 8 9 10 11 12 13
  10. export interface TodoState { items: Todo[]; loading: boolean; } export

    const initialState: TodoState = { items: [], loading: false, }; export const TodoStore = signalStore( withState(initialState), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 export interface TodoState { items: Todo[]; loading: boolean; } 1 2 3 4 5 export const initialState: TodoState = { 6 items: [], 7 loading: false, 8 }; 9 10 export const TodoStore = signalStore( 11 withState(initialState), 12 ); 13
  11. export interface TodoState { items: Todo[]; loading: boolean; } export

    const initialState: TodoState = { items: [], loading: false, }; export const TodoStore = signalStore( withState(initialState), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 export interface TodoState { items: Todo[]; loading: boolean; } 1 2 3 4 5 export const initialState: TodoState = { 6 items: [], 7 loading: false, 8 }; 9 10 export const TodoStore = signalStore( 11 withState(initialState), 12 ); 13 export const initialState: TodoState = { items: [], loading: false, }; export interface TodoState { 1 items: Todo[]; 2 loading: boolean; 3 } 4 5 6 7 8 9 10 export const TodoStore = signalStore( 11 withState(initialState), 12 ); 13
  12. export interface TodoState { items: Todo[]; loading: boolean; } export

    const initialState: TodoState = { items: [], loading: false, }; export const TodoStore = signalStore( withState(initialState), ); 1 2 3 4 5 6 7 8 9 10 11 12 13 export interface TodoState { items: Todo[]; loading: boolean; } 1 2 3 4 5 export const initialState: TodoState = { 6 items: [], 7 loading: false, 8 }; 9 10 export const TodoStore = signalStore( 11 withState(initialState), 12 ); 13 export const initialState: TodoState = { items: [], loading: false, }; export interface TodoState { 1 items: Todo[]; 2 loading: boolean; 3 } 4 5 6 7 8 9 10 export const TodoStore = signalStore( 11 withState(initialState), 12 ); 13 export const TodoStore = signalStore( withState(initialState), ); export interface TodoState { 1 items: Todo[]; 2 loading: boolean; 3 } 4 5 export const initialState: TodoState = { 6 items: [], 7 loading: false, 8 }; 9 10 11 12 13
  13. export const TodoStore = signalStore( withState({ /* ... */ }),

    withMethods((...) => ({ // ... })) ); 1 2 3 4 5 6
  14. export const TodoStore = signalStore( withState({ /* ... */ }),

    withMethods((...) => ({ // ... })) ); 1 2 3 4 5 6 withMethods((...) => ({ // ... })) export const TodoStore = signalStore( 1 withState({ /* ... */ }), 2 3 4 5 ); 6
  15. export const TodoStore = signalStore( withState({ /* ... */ ),

    withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos() { // use Todoservice and then patchState(store, { items }); }, })) ); 1 2 3 4 5 6 7 8 9
  16. export const TodoStore = signalStore( withState({ /* ... */ ),

    withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos() { // use Todoservice and then patchState(store, { items }); }, })) ); 1 2 3 4 5 6 7 8 9 withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos() { // use Todoservice and then patchState(store, { items }); }, })) export const TodoStore = signalStore( 1 withState({ /* ... */ ), 2 3 4 5 6 7 8 ); 9
  17. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
  18. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 })) 18 ); 19
  19. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 })) 18 ); 19 patchState(store, {loading: true}); export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos: rxMethod( 5 switchMap(() => { 6 7 8 return todoService.getItems().pipe( 9 tapResponse({ 10 next: (items) => patchState(store, {items}), 11 error: console.error, 12 finalize: () => patchState(store, {loading: false}), 13 }) 14 ); 15 }) 16 ), 17 })) 18 ); 19
  20. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 })) 18 ); 19 patchState(store, {loading: true}); export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos: rxMethod( 5 switchMap(() => { 6 7 8 return todoService.getItems().pipe( 9 tapResponse({ 10 next: (items) => patchState(store, {items}), 11 error: console.error, 12 finalize: () => patchState(store, {loading: false}), 13 }) 14 ); 15 }) 16 ), 17 })) 18 ); 19 return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos: rxMethod( 5 switchMap(() => { 6 patchState(store, {loading: true}); 7 8 9 10 11 12 13 14 15 }) 16 ), 17 })) 18 ); 19
  21. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 loadAllTodos: rxMethod( switchMap(() => { patchState(store, {loading: true}); return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); }) ), export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 })) 18 ); 19 patchState(store, {loading: true}); export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos: rxMethod( 5 switchMap(() => { 6 7 8 return todoService.getItems().pipe( 9 tapResponse({ 10 next: (items) => patchState(store, {items}), 11 error: console.error, 12 finalize: () => patchState(store, {loading: false}), 13 }) 14 ); 15 }) 16 ), 17 })) 18 ); 19 return todoService.getItems().pipe( tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) ); export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos: rxMethod( 5 switchMap(() => { 6 patchState(store, {loading: true}); 7 8 9 10 11 12 13 14 15 }) 16 ), 17 })) 18 ); 19 tapResponse({ next: (items) => patchState(store, {items}), error: console.error, finalize: () => patchState(store, {loading: false}), }) export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos: rxMethod( 5 switchMap(() => { 6 patchState(store, {loading: true}); 7 8 return todoService.getItems().pipe( 9 10 11 12 13 14 ); 15 }) 16 ), 17 })) 18 ); 19
  22. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos(store, todoService: TodoService) { ... }, async loadAllTodosByPromise() { patchState(store, { loading: true }); const items = await todoService.getItemsAsPromise(); patchState(store, { items, loading: false }); }, })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  23. export const TodoStore = signalStore( { providedIn: 'root' }, withState({

    /* state goes here */ ), withMethods((store, todoService = inject(TodoService)) => ({ loadAllTodos(store, todoService: TodoService) { ... }, async loadAllTodosByPromise() { patchState(store, { loading: true }); const items = await todoService.getItemsAsPromise(); patchState(store, { items, loading: false }); }, })) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 async loadAllTodosByPromise() { patchState(store, { loading: true }); const items = await todoService.getItemsAsPromise(); patchState(store, { items, loading: false }); }, export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState({ /* state goes here */ ), 3 withMethods((store, todoService = inject(TodoService)) => ({ 4 loadAllTodos(store, todoService: TodoService) { ... }, 5 6 7 8 9 10 11 12 13 })) 14 ); 15
  24. @Component({ // ... providers: [TodoStore], }) export class AppComponent implements

    OnInit { readonly store = inject(TodoStore); ngOnInit() { this.store.loadAllTodos(); } } 1 2 3 4 5 6 7 8 9 10 11
  25. @Component({ // ... providers: [TodoStore], }) export class AppComponent implements

    OnInit { readonly store = inject(TodoStore); ngOnInit() { this.store.loadAllTodos(); } } 1 2 3 4 5 6 7 8 9 10 11 providers: [TodoStore], @Component({ 1 // ... 2 3 }) 4 export class AppComponent implements OnInit { 5 readonly store = inject(TodoStore); 6 7 ngOnInit() { 8 this.store.loadAllTodos(); 9 } 10 } 11
  26. @Component({ // ... providers: [TodoStore], }) export class AppComponent implements

    OnInit { readonly store = inject(TodoStore); ngOnInit() { this.store.loadAllTodos(); } } 1 2 3 4 5 6 7 8 9 10 11 providers: [TodoStore], @Component({ 1 // ... 2 3 }) 4 export class AppComponent implements OnInit { 5 readonly store = inject(TodoStore); 6 7 ngOnInit() { 8 this.store.loadAllTodos(); 9 } 10 } 11 readonly store = inject(TodoStore); @Component({ 1 // ... 2 providers: [TodoStore], 3 }) 4 export class AppComponent implements OnInit { 5 6 7 ngOnInit() { 8 this.store.loadAllTodos(); 9 } 10 } 11
  27. @Component({ // ... providers: [TodoStore], }) export class AppComponent implements

    OnInit { readonly store = inject(TodoStore); ngOnInit() { this.store.loadAllTodos(); } } 1 2 3 4 5 6 7 8 9 10 11 providers: [TodoStore], @Component({ 1 // ... 2 3 }) 4 export class AppComponent implements OnInit { 5 readonly store = inject(TodoStore); 6 7 ngOnInit() { 8 this.store.loadAllTodos(); 9 } 10 } 11 readonly store = inject(TodoStore); @Component({ 1 // ... 2 providers: [TodoStore], 3 }) 4 export class AppComponent implements OnInit { 5 6 7 ngOnInit() { 8 this.store.loadAllTodos(); 9 } 10 } 11 this.store.loadAllTodos(); @Component({ 1 // ... 2 providers: [TodoStore], 3 }) 4 export class AppComponent implements OnInit { 5 readonly store = inject(TodoStore); 6 7 ngOnInit() { 8 9 } 10 } 11
  28. template: `{{ store.items() }} {{ store.loading() }}`, readonly store =

    inject(TodoStore); @Component({ 1 // ... 2 3 providers: [TodoStore], 4 }) 5 export class AppComponent implements OnInit { 6 7 8 ngOnInit() { 9 this.store.loadAllTodos(); 10 } 11 } 12
  29. export const TodoStore = signalStore( { providedIn: 'root' }, withState(initialState),

    withMethods(/* ... */), withHooks({ // Hooks }) ); 1 2 3 4 5 6 7 8
  30. export const TodoStore = signalStore( { providedIn: 'root' }, withState(initialState),

    withMethods(/* ... */), withHooks({ // Hooks }) ); 1 2 3 4 5 6 7 8 withHooks({ // Hooks }) ); export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState(initialState), 3 withMethods(/* ... */), 4 5 6 7 8
  31. export const TodoStore = signalStore( { providedIn: 'root' }, withState(initialState),

    withMethods(/* ... */), withHooks({ onInit({ loadAllTodos }) { loadAllTodos(); }, onDestroy() { console.log('on destroy'); }, }) ); 1 2 3 4 5 6 7 8 9 10 11 12 13
  32. export const TodoStore = signalStore( { providedIn: 'root' }, withState(initialState),

    withMethods(/* ... */), withHooks({ onInit({ loadAllTodos }) { loadAllTodos(); }, onDestroy() { console.log('on destroy'); }, }) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 withHooks({ onInit({ loadAllTodos }) { loadAllTodos(); }, onDestroy() { console.log('on destroy'); }, }) export const TodoStore = signalStore( 1 { providedIn: 'root' }, 2 withState(initialState), 3 withMethods(/* ... */), 4 5 6 7 8 9 10 11 12 ); 13
  33. @Component({ // ... providers: [TodoStore], }) export class AppComponent implements

    OnInit { readonly store = inject(TodoStore); ngOnInit() { this.store.loadAllTodos(); } } 1 2 3 4 5 6 7 8 9 10 11
  34. @Component({ // ... providers: [TodoStore], }) export class AppComponent {

    readonly store = inject(TodoStore); } 1 2 3 4 5 6 7
  35. withComputed((state) => ({ /* ... */ })), export const TodoStore

    = signalStore( 1 withState(initialState), 2 3 4 5 6 7 withMethods(/* ... */), 8 withHooks(/* ... */) 9 ); 10
  36. export const TodoStore = signalStore( withState(initialState), withComputed(({ items }) =>

    ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), withMethods(/* ... */), withHooks(/* ... */) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
  37. export const TodoStore = signalStore( withState(initialState), withComputed(({ items }) =>

    ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), withMethods(/* ... */), withHooks(/* ... */) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 withComputed(({ items }) => ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), export const TodoStore = signalStore( 1 withState(initialState), 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21
  38. export const TodoStore = signalStore( withState(initialState), withComputed(({ items }) =>

    ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), withMethods(/* ... */), withHooks(/* ... */) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 withComputed(({ items }) => ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), export const TodoStore = signalStore( 1 withState(initialState), 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21 doneCount: computed(() => items().filter((x) => x.done).length), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(({ items }) => ({ 4 5 undoneCount: computed(() => items().filter((x) => !x.done).length), 6 percentageDone: computed(() => { 7 const done = items().filter((x) => x.done).length; 8 const total = items().length; 9 10 if (total === 0) { 11 return 0; 12 } 13 14 return (done / total) * 100; 15 }), 16 })), 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21
  39. export const TodoStore = signalStore( withState(initialState), withComputed(({ items }) =>

    ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), withMethods(/* ... */), withHooks(/* ... */) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 withComputed(({ items }) => ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), export const TodoStore = signalStore( 1 withState(initialState), 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21 doneCount: computed(() => items().filter((x) => x.done).length), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(({ items }) => ({ 4 5 undoneCount: computed(() => items().filter((x) => !x.done).length), 6 percentageDone: computed(() => { 7 const done = items().filter((x) => x.done).length; 8 const total = items().length; 9 10 if (total === 0) { 11 return 0; 12 } 13 14 return (done / total) * 100; 15 }), 16 })), 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21 undoneCount: computed(() => items().filter((x) => !x.done).length), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(({ items }) => ({ 4 doneCount: computed(() => items().filter((x) => x.done).length), 5 6 percentageDone: computed(() => { 7 const done = items().filter((x) => x.done).length; 8 const total = items().length; 9 10 if (total === 0) { 11 return 0; 12 } 13 14 return (done / total) * 100; 15 }), 16 })), 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21
  40. export const TodoStore = signalStore( withState(initialState), withComputed(({ items }) =>

    ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), withMethods(/* ... */), withHooks(/* ... */) ); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 withComputed(({ items }) => ({ doneCount: computed(() => items().filter((x) => x.done).length), undoneCount: computed(() => items().filter((x) => !x.done).length), percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), })), export const TodoStore = signalStore( 1 withState(initialState), 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21 doneCount: computed(() => items().filter((x) => x.done).length), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(({ items }) => ({ 4 5 undoneCount: computed(() => items().filter((x) => !x.done).length), 6 percentageDone: computed(() => { 7 const done = items().filter((x) => x.done).length; 8 const total = items().length; 9 10 if (total === 0) { 11 return 0; 12 } 13 14 return (done / total) * 100; 15 }), 16 })), 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21 undoneCount: computed(() => items().filter((x) => !x.done).length), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(({ items }) => ({ 4 doneCount: computed(() => items().filter((x) => x.done).length), 5 6 percentageDone: computed(() => { 7 const done = items().filter((x) => x.done).length; 8 const total = items().length; 9 10 if (total === 0) { 11 return 0; 12 } 13 14 return (done / total) * 100; 15 }), 16 })), 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21 percentageDone: computed(() => { const done = items().filter((x) => x.done).length; const total = items().length; if (total === 0) { return 0; } return (done / total) * 100; }), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(({ items }) => ({ 4 doneCount: computed(() => items().filter((x) => x.done).length), 5 undoneCount: computed(() => items().filter((x) => !x.done).length), 6 7 8 9 10 11 12 13 14 15 16 })), 17 18 withMethods(/* ... */), 19 withHooks(/* ... */) 20 ); 21
  41. @Component({ providers: [TodoStore], templates: ` <div> {{ store.doneCount() }} /

    {{ store.undoneCount() }} {{ store.percentageDone() }} </div> ` }) export class AppComponent implements OnInit { readonly store = inject(TodoStore); } 1 2 3 4 5 6 7 8 9 10 11
  42. @Component({ providers: [TodoStore], templates: ` <div> {{ store.doneCount() }} /

    {{ store.undoneCount() }} {{ store.percentageDone() }} </div> ` }) export class AppComponent implements OnInit { readonly store = inject(TodoStore); } 1 2 3 4 5 6 7 8 9 10 11 <div> {{ store.doneCount() }} / {{ store.undoneCount() }} {{ store.percentageDone() }} </div> ` @Component({ 1 providers: [TodoStore], 2 templates: ` 3 4 5 6 7 }) 8 export class AppComponent implements OnInit { 9 readonly store = inject(TodoStore); 10 } 11
  43. import { computed } from '@angular/core'; import { signalStoreFeature, withComputed,

    withState } from '@ngrx/signals'; export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; export type RequestStatusState = { requestStatus: RequestStatus }; export function withRequestStatus() { return signalStoreFeature( withState<RequestStatusState>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), })) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
  44. import { computed } from '@angular/core'; import { signalStoreFeature, withComputed,

    withState } from '@ngrx/signals'; export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; export type RequestStatusState = { requestStatus: RequestStatus }; export function withRequestStatus() { return signalStoreFeature( withState<RequestStatusState>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), })) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export function withRequestStatus() { import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22
  45. import { computed } from '@angular/core'; import { signalStoreFeature, withComputed,

    withState } from '@ngrx/signals'; export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; export type RequestStatusState = { requestStatus: RequestStatus }; export function withRequestStatus() { return signalStoreFeature( withState<RequestStatusState>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), })) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export function withRequestStatus() { import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 return signalStoreFeature( import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22
  46. import { computed } from '@angular/core'; import { signalStoreFeature, withComputed,

    withState } from '@ngrx/signals'; export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; export type RequestStatusState = { requestStatus: RequestStatus }; export function withRequestStatus() { return signalStoreFeature( withState<RequestStatusState>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), })) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export function withRequestStatus() { import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 return signalStoreFeature( import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 withState<RequestStatusState>({ requestStatus: 'idle' }), import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 return signalStoreFeature( 8 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22
  47. import { computed } from '@angular/core'; import { signalStoreFeature, withComputed,

    withState } from '@ngrx/signals'; export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; export type RequestStatusState = { requestStatus: RequestStatus }; export function withRequestStatus() { return signalStoreFeature( withState<RequestStatusState>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), })) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export function withRequestStatus() { import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 return signalStoreFeature( import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 withState<RequestStatusState>({ requestStatus: 'idle' }), import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 return signalStoreFeature( 8 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 withComputed(({ requestStatus }) => ({ import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22
  48. import { computed } from '@angular/core'; import { signalStoreFeature, withComputed,

    withState } from '@ngrx/signals'; export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; export type RequestStatusState = { requestStatus: RequestStatus }; export function withRequestStatus() { return signalStoreFeature( withState<RequestStatusState>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), })) ); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 export function withRequestStatus() { import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 return signalStoreFeature( import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 withState<RequestStatusState>({ requestStatus: 'idle' }), import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 return signalStoreFeature( 8 9 withComputed(({ requestStatus }) => ({ 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 withComputed(({ requestStatus }) => ({ import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 10 isPending: computed(() => requestStatus() === 'pending'), 11 12 isFulfilled: computed(() => requestStatus() === 'fulfilled'), 13 14 error: computed(() => { 15 const status = requestStatus(); 16 17 return typeof status === 'object' ? status.error : null; 18 }), 19 })) 20 ); 21 } 22 isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), error: computed(() => { const status = requestStatus(); return typeof status === 'object' ? status.error : null; }), import { computed } from '@angular/core'; 1 import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; 2 3 export type RequestStatus = 'idle' | 'pending' | 'fulfilled' | { error: string }; 4 export type RequestStatusState = { requestStatus: RequestStatus }; 5 6 export function withRequestStatus() { 7 return signalStoreFeature( 8 withState<RequestStatusState>({ requestStatus: 'idle' }), 9 withComputed(({ requestStatus }) => ({ 10 11 12 13 14 15 16 17 18 19 })) 20 ); 21 } 22
  49. export function setPending(): RequestStatusState { return { requestStatus: 'pending' };

    } export function setFulfilled(): RequestStatusState { return { requestStatus: 'fulfilled' }; } export function setError(error: string): RequestStatusState { return { requestStatus: { error } }; } 1 2 3 4 5 6 7 8 9 10 11
  50. export const TodoStore = signalStore( withState(initialState), withRequestStatus(), withComputed(/* ... */),

    withMethods(/* ... */), withHooks(/* ... */) ); readonly store = inject(TodoStore); store.requestStatus(); store.isPending(); store.isFulfilled(); 1 2 3 4 5 6 7 8 9 10 11 12 13
  51. export const TodoStore = signalStore( withState(initialState), withRequestStatus(), withComputed(/* ... */),

    withMethods(/* ... */), withHooks(/* ... */) ); readonly store = inject(TodoStore); store.requestStatus(); store.isPending(); store.isFulfilled(); 1 2 3 4 5 6 7 8 9 10 11 12 13 withRequestStatus(), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(/* ... */), 4 withMethods(/* ... */), 5 withHooks(/* ... */) 6 ); 7 8 readonly store = inject(TodoStore); 9 10 store.requestStatus(); 11 store.isPending(); 12 store.isFulfilled(); 13
  52. export const TodoStore = signalStore( withState(initialState), withRequestStatus(), withComputed(/* ... */),

    withMethods(/* ... */), withHooks(/* ... */) ); readonly store = inject(TodoStore); store.requestStatus(); store.isPending(); store.isFulfilled(); 1 2 3 4 5 6 7 8 9 10 11 12 13 withRequestStatus(), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(/* ... */), 4 withMethods(/* ... */), 5 withHooks(/* ... */) 6 ); 7 8 readonly store = inject(TodoStore); 9 10 store.requestStatus(); 11 store.isPending(); 12 store.isFulfilled(); 13 readonly store = inject(TodoStore); export const TodoStore = signalStore( 1 withState(initialState), 2 withRequestStatus(), 3 withComputed(/* ... */), 4 withMethods(/* ... */), 5 withHooks(/* ... */) 6 ); 7 8 9 10 store.requestStatus(); 11 store.isPending(); 12 store.isFulfilled(); 13
  53. export const TodoStore = signalStore( withState(initialState), withRequestStatus(), withComputed(/* ... */),

    withMethods(/* ... */), withHooks(/* ... */) ); readonly store = inject(TodoStore); store.requestStatus(); store.isPending(); store.isFulfilled(); 1 2 3 4 5 6 7 8 9 10 11 12 13 withRequestStatus(), export const TodoStore = signalStore( 1 withState(initialState), 2 3 withComputed(/* ... */), 4 withMethods(/* ... */), 5 withHooks(/* ... */) 6 ); 7 8 readonly store = inject(TodoStore); 9 10 store.requestStatus(); 11 store.isPending(); 12 store.isFulfilled(); 13 readonly store = inject(TodoStore); export const TodoStore = signalStore( 1 withState(initialState), 2 withRequestStatus(), 3 withComputed(/* ... */), 4 withMethods(/* ... */), 5 withHooks(/* ... */) 6 ); 7 8 9 10 store.requestStatus(); 11 store.isPending(); 12 store.isFulfilled(); 13 store.requestStatus(); store.isPending(); store.isFulfilled(); export const TodoStore = signalStore( 1 withState(initialState), 2 withRequestStatus(), 3 withComputed(/* ... */), 4 withMethods(/* ... */), 5 withHooks(/* ... */) 6 ); 7 8 readonly store = inject(TodoStore); 9 10 11 12 13