Lab 18: Signal Store
π Resourcesβ
π Starter Codeβ
step-19-album-wholesale-v21-post-lazy
In this lab, you'll implement centralized state management using NgRx SignalStore. You'll install @ngrx/signals, create a store with state, computed values, and methods using withState/withComputed/withMethods, and manage async operations with rxMethod.
π Instructionsβ
Step 1: Install @ngrx/signalsβ
npm install @ngrx/signals
Step 2: Create Signal Storeβ
Create a store with state, computed values, and methods:
import { signalStore, withState, withMethods, withComputed, patchState } from '@ngrx/signals';
interface AlbumState {
albums: Album[];
loading: boolean;
}
export const AlbumStore = signalStore(
{ providedIn: 'root' },
withState<AlbumState>({
albums: [],
loading: false
}),
withComputed(({ albums }) => ({
totalAlbums: computed(() => albums().length)
})),
withMethods((store, http = inject(HttpClient)) => ({
loadAlbums: rxMethod<void>(
pipe(
tap(() => patchState(store, { loading: true })),
switchMap(() => http.get<Album[]>('/api/albums')),
tap(albums => patchState(store, { albums, loading: false }))
)
)
}))
);
Step 3: Use Store in Componentβ
Inject and use the store:
export class AlbumListComponent implements OnInit {
albumStore = inject(AlbumStore);
ngOnInit() {
this.albumStore.loadAlbums();
}
}
Template:
@if (albumStore.loading()) {
<p>Loading...</p>
}
@for (album of albumStore.albums(); track album.id) {
<app-album-card [album]="album"></app-album-card>
}
Step 4: Update State with patchStateβ
Use patchState() to update store state:
// Update single property
patchState(store, { loading: true });
// Update multiple properties
patchState(store, { albums: newAlbums, loading: false });
// Use function for complex updates
patchState(store, state => ({
albums: [...state.albums, newAlbum]
}));