Create a Signal Store

Guidelines for creating an NgRx Signal Store in an Angular project, using rxMethod, tapResponse, and notification handling.

Sby Skills Guide Bot
DevelopmentIntermediate
307/23/2026
CursorWindsurfCopilotCodex
#signal-store#ngrx#angular#state-management#rxmethod

Recommended for


name: create-signal-store description: Use when the user asks to add state management or create a store for a feature in this Angular workspace.

Creating a Signal Store

In this workspace we manage state exclusively with the NgRx Signal Store. When asked to create a store, follow these rules:

  • Create the store with signalStore from @ngrx/signals.
  • Decide providedIn: 'root' vs. component-provided scope using the placement test in the state-management skill — don't default to root.
  • Keep collections with withEntities<T>(); keep flags and scalar values with withState({ ... }).
  • Implement every asynchronous action as an rxMethod and wrap the HTTP call in tapResponse. Track loading with a loading flag kept in withState({ loading: false }): set it to true before the call in a leading tap, and back to false when the data arrives.
  • On success, patch the state AND show a success notification through the injected NotificationService. On error, show an error notification.
  • Inject services through default parameters of the withMethods factory.
  • If the store should load its data immediately, call the load method from a withHooks({ onInit }) hook.

Example

export const DogsStore = signalStore(
  { providedIn: 'root' },
  withEntities<Dog>(),
  withState({ loading: false }),
  withMethods(
    (
      store,
      notificationService = inject(NotificationService),
      dogsApiService = inject(DogsApiService),
    ) => ({
      loadDogs: rxMethod<void>(
        pipe(
          tap(() => patchState(store, { loading: true })),
          exhaustMap(() =>
            dogsApiService.getDogs().pipe(
              tapResponse({
                next: (dogs) => {
                  patchState(store, setAllEntities(dogs), { loading: false });
                  notificationService.showSuccess('Dogs Loaded');
                },
                error: () => notificationService.showError(),
              }),
            ),
          ),
        ),
      ),
    }),
  ),
  withHooks({
    onInit(store) {
      store.loadDogs();
    },
  }),
);
Related skills