### Initialize the @ngrx example application Source: https://github.com/ngrx/platform/blob/main/projects/example-app/README.md Commands to clone the repository, install dependencies, and start the development server. ```bash # Clone the repository git clone https://github.com/ngrx/platform.git # Go to the example directory cd platform # Install the dependencies pnpm install # Start the server pnpm exec nx serve example-app ``` -------------------------------- ### Install Dependencies Source: https://github.com/ngrx/platform/blob/main/CONTRIBUTING.md Run this command to install all necessary development dependencies for the project. ```shell pnpm install ``` -------------------------------- ### Action Generation Examples Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/action.md Common usage patterns for generating action files with different configuration flags. ```sh ng generate action User ``` ```sh ng generate action User --flat false ``` ```sh ng generate action User --group ``` -------------------------------- ### Generate Selector Examples Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/selector.md Common usage patterns for generating selector files with and without grouping. ```sh ng generate selector User ``` ```sh ng generate selector User --group ``` -------------------------------- ### NgRx Store DevTools Setup in app.config.ts Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store-devtools/config.md Example of setting up NgRx Store DevTools in an Angular application's configuration file. This includes setting maxAge, logOnly, autoPause, and specific features for the DevTools. ```typescript export const appConfig: ApplicationConfig = { providers: [ provideStoreDevtools({ maxAge: 25, logOnly: false, autoPause: true, features: { pause: false, lock: true, persist: true, }, }), ], }; ``` -------------------------------- ### Example Commit Message: Docs Source: https://github.com/ngrx/platform/blob/main/CONTRIBUTING.md An example of a commit message for documentation changes, specifying the type and scope. ```git docs(changelog): update changelog to beta.5 ``` -------------------------------- ### Register Custom Data Service - Generic Example Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/data/entity-dataservice.md Shows a generic example of how to register a custom data service with `entityDataService.registerService()`, adhering to the `EntityCollectionDataService` interface. ```typescript // Register custom data service entityDataService.registerService('Hero', peculiarHeroDataService); ``` -------------------------------- ### Install NgRx Store with Angular CLI Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/install.md Use the Angular CLI to automatically add NgRx Store to your project dependencies and configure the initial module setup. ```sh ng add @ngrx/store@latest ``` ```sh ng add @ngrx/store@latest --no-minimal ``` -------------------------------- ### Manually install @ngrx/eslint-plugin with npm Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/install.md Install the @ngrx/eslint-plugin package as a development dependency using npm. ```sh npm install @ngrx/eslint-plugin --save-dev ``` -------------------------------- ### Configure global store name Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/use-consistent-global-store-name.md Configuration example to change the preferred global store name from the default 'store' to 'store$'. ```json "rules": { "@ngrx/use-consistent-global-store-name": ["warn", "store$"] } ``` -------------------------------- ### Install @ngrx/operators with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/operators/install.md Use the Angular CLI to automatically add the dependency to package.json and install it. ```sh ng add @ngrx/operators@latest ``` -------------------------------- ### Correct usage of dispatch Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/prefer-action-creator-in-dispatch.md These examples show the preferred pattern of using action creator functions for dispatching. ```ts store$.dispatch(action); this.store$.dispatch(BookActions.load()); this.store$.dispatch(AuthActions.Login({ payload })); ``` -------------------------------- ### Manually install @ngrx/eslint-plugin with yarn Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/install.md Install the @ngrx/eslint-plugin package as a development dependency using yarn. ```sh yarn add @ngrx/eslint-plugin -D ``` -------------------------------- ### Manual Installation with yarn Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/router-store/install.md Install the NgRx Router Store manually using yarn. This command adds the package to your project's dependencies. ```sh yarn add @ngrx/router-store ``` -------------------------------- ### Install Store Devtools with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store-devtools/install.md Use the Angular CLI to automatically add the Store Devtools dependency and configure the provider. ```sh ng add @ngrx/store-devtools@latest ``` -------------------------------- ### Install ComponentStore via Angular CLI Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/component-store/install.md Use the Angular CLI to automatically add the dependency and update package configuration. ```sh ng add @ngrx/component-store@latest ``` -------------------------------- ### Install @ngrx/data manually with npm Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/data/install.md Manually install the @ngrx/data package using npm. This is an alternative to the `ng add` command. ```sh npm install @ngrx/data ``` -------------------------------- ### Manual Installation with npm Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/router-store/install.md Install the NgRx Router Store manually using npm. This command adds the package to your project's dependencies. ```sh npm install @ngrx/router-store ``` -------------------------------- ### Install @ngrx/data manually with yarn Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/data/install.md Manually install the @ngrx/data package using yarn. This is an alternative to the `ng add` command. ```sh yarn add @ngrx/data ``` -------------------------------- ### Manual Installation of NgRx Entity Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/entity/install.md Alternative method for installing the NgRx Entity package manually using npm or yarn. ```sh npm install @ngrx/entity --save ``` ```sh yarn add @ngrx/entity ``` -------------------------------- ### Correct Updater Implementation Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/updater-explicit-return-type.md This example demonstrates the correct usage by explicitly defining the return type for the updater method. ```ts interface MoviesState { movies: Movie[]; } class MoviesStore extends ComponentStore { readonly addMovie = this.updater( (state, movie: Movie): MoviesState => ({ movies: [...state.movies, movie], // ⚠ this does throw extra: 'property', }) ); } ``` -------------------------------- ### Plain Old JavaScript Object (POJO) Action Example Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/actions.md An example of an action represented as a plain JavaScript object. The 'type' property follows the '[Source] Event' convention for clarity. ```json { "type": "[Auth API] Login Success" } ``` -------------------------------- ### Generate Container with State and Interface Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/container.md Example of generating a container component specifying the state file and a custom state interface name. ```sh ng generate container UsersPage --state reducers/index.ts --state-interface MyState ``` -------------------------------- ### Paginator Component Implementation Patterns Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/component-store/usage.md Examples comparing a component providing ComponentStore directly versus using a separate PaginatorStore service. ```typescript ``` ```typescript ``` ```typescript ``` -------------------------------- ### Correct Implementation of OnInitEffects Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/use-effects-lifecycle-interface.md This example shows the correct implementation of `ngrxOnInitEffects` by ensuring the class implements the `OnInitEffects` interface. ```typescript import { OnInitEffects } from '@ngrx/effects'; class Effect implements OnInitEffects { ngrxOnInitEffects(): Action { return { type: '[Effect] Init' }; } } ``` -------------------------------- ### Strict Selector Projector behavior Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v15.md Examples showing the transition to type-safe projector functions in @ngrx/store. ```ts const mySelector = createSelector( () => 'one', () => 2, (one, two) => 3 ); mySelector.projector(); // <- type is projector(...args: any[]): number ``` ```ts const mySelector = createSelector( () => 'one', () => 2, (one, two) => 3 ); mySelector.projector(); // <- Results in type error. Type is projector(s1: string, s2: number): number ``` ```ts const mySelector = createSelector( () => 'one', () => 2, (one, two) => 3 )(mySelector.projector as any)(); ``` -------------------------------- ### Action with Metadata Example Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/actions.md This action includes additional properties ('username', 'password') to provide metadata for the event. This is useful for passing data related to the action. ```json { type: '[Login Page] Login', username: string; password: string; } ``` -------------------------------- ### Install NgRx Router Store with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/router-store/install.md Use this command to automatically add and configure the NgRx Router Store to your project. It updates dependencies, installs them, and configures the `StoreRouterConnectingModule`. ```sh ng add @ngrx/router-store@latest ``` -------------------------------- ### Install @ngrx/eslint-plugin with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/install.md Use this command to add the ESLint plugin to your project. You will be prompted to select a configuration. ```sh ng add @ngrx/eslint-plugin ``` -------------------------------- ### Implement Eager OnStateInit in ComponentStore Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/component-store/lifecycle.md The OnStateInit hook executes once after the initial state is set. This example demonstrates eager initialization via the constructor. ```ts export interface BooksState { collection: Book[]; } export const initialState: BooksState = { collection: [], }; @Injectable() export class BooksStore extends ComponentStore implements OnStateInit { constructor() { // eager state initialization super(initialState); } ngrxOnStateInit() { // called once after state has been first initialized } } ``` ```ts @Component({ // ... other metadata providers: [provideComponentStore(BooksStore)], }) export class BooksPageComponent { constructor(private booksStore: BooksStore) {} } ``` -------------------------------- ### Action Creator Props (After) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v13.md Example of an action created with `createAction` using an object type for props, which is the required format. ```ts const action = createAction( '[Source] Event', props<{ name: string }>() ); ``` -------------------------------- ### Correct usage of signalState Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/signal-state-no-arrays-at-root-level.md Examples of valid initial states using objects or properties containing arrays. ```ts const store = withState({ foo: 'bar' }); const store = withState({ arrayAsProperty: ['foo', 'bar'] }); const initialState = {}; const store = signalStore(withState(initialState)); ``` -------------------------------- ### Handling Init Action with defer() Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v4.md The `@ngrx/store/init` action now fires prior to effects starting. Use `defer()` for the same behavior as the previous `switchMap` approach. ```typescript import { Dispatcher, Action } from '@ngrx/store'; import { Actions, Effect } from '@ngrx/effects'; import * as auth from '../actions/auth.actions'; @Injectable() export class AppEffects { @Effect() init$: Observable = this.actions$ .ofType(Dispatcher.INIT) .switchMap((action) => { return of(new auth.LoginAction()); }); constructor(private actions$: Actions) {} } ``` ```typescript import { Action } from '@ngrx/store'; import { Actions, Effect } from '@ngrx/effects'; import { defer } from 'rxjs'; import * as auth from '../actions/auth.actions'; @Injectable() export class AppEffects { @Effect() init$: Observable = defer(() => { return of(new auth.LoginAction()); }); constructor(private actions$: Actions) {} } ``` -------------------------------- ### Install @ngrx/component with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/component/install.md Use the Angular CLI to automatically add the package and update project dependencies. ```sh ng add @ngrx/component@latest ``` -------------------------------- ### Correct global store naming Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/use-consistent-global-store-name.md Example of consistent naming where all classes use the same variable name for the Store injection. ```ts export class ClassOne { constructor(private store: Store) {} } export class ClassTwo { constructor(private store: Store) {} } ``` -------------------------------- ### Correct Implementation of OnRunEffects Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/use-effects-lifecycle-interface.md This example demonstrates the correct implementation of `ngrxOnRunEffects` by implementing the `OnRunEffects` interface, ensuring proper effect execution. ```typescript import { OnRunEffects } from '@ngrx/effects'; class Effect implements OnRunEffects { constructor(private actions$: Actions) {} ngrxOnRunEffects(resolvedEffects$: Observable) { return this.actions$.pipe( ofType('LOGGED_IN'), exhaustMap(() => resolvedEffects$.pipe( takeUntil(this.actions$.pipe(ofType('LOGGED_OUT'))) ) ) ); } } ``` -------------------------------- ### Generate Initial Store Setup Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/store.md Use this command to generate the initial state management files and register them within the application's root module. ```sh ng generate store State --root --module app.module.ts ``` -------------------------------- ### Logging Meta-reducer Example Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/metareducers.md This meta-reducer logs the current state and action to the console before passing them to the next reducer. It's useful for debugging. ```typescript import { StoreModule, ActionReducer, MetaReducer } from '@ngrx/store'; import { reducers } from './reducers'; // console.log all actions export function debug( reducer: ActionReducer ): ActionReducer { return function (state, action) { console.log('state', state); console.log('action', action); return reducer(state, action); }; } export const metaReducers: MetaReducer[] = [debug]; @NgModule({ imports: [StoreModule.forRoot(reducers, { metaReducers })], }) export class AppModule {} ``` -------------------------------- ### Incorrect Selector Naming Conventions Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/prefix-selectors-with-select.md Examples of selector functions that violate the 'select' prefix convention. This includes selectors without any prefix, with a 'get' prefix, improper casing, or when using `createSelectorFactory` without the 'select' prefix. ```typescript // ⚠ Usage of a selector without any prefix export const feature = createSelector( (state: AppState) => state.feature ); // ⚠ Usage of a selector without any description export const select = (id: string) => createSelector((state: AppState) => state.feature); // ⚠ Usage of a selector with a `get` prefix export const getFeature: MemoizedSelector = ( state: AppState ) => state.feature; // ⚠ Usage of a selector with improper casing const selectfeature = createFeatureSelector( featureKey ); // ⚠ Usage of a `createSelectorFactory` without `select` prefix const createSelector = createSelectorFactory((projectionFun) => defaultMemoize( projectionFun, orderDoesNotMatterComparer, orderDoesNotMatterComparer ) ); ``` -------------------------------- ### Install NgRx Dependencies with yarn Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/index.md Installs the core NgRx packages using yarn. Ensure you have NgRx schematics installed first. ```sh yarn add @ngrx/{store,effects,entity,store-devtools} ``` -------------------------------- ### Create MockStore with Injector.create Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/testing.md Demonstrates creating a MockStore instance using Injector.create for testing components without TestBed. Requires importing MockStore and provideMockStore. ```typescript import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { Injector } from '@angular/core'; describe('Books Component', () => { let store: MockStore; const initialState = { books: ['Book 1', 'Book 2', 'Book 3'] }; beforeEach(() => { const injector = Injector.create({ providers: [provideMockStore({ initialState })], }); store = injector.get(MockStore); }); }); ``` -------------------------------- ### Install NgRx Dependencies with npm Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/index.md Installs the core NgRx packages using npm. Ensure you have NgRx schematics installed first. ```sh npm install @ngrx/{store,effects,entity,store-devtools} --save ``` -------------------------------- ### Correct Effect Implementation Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/no-multiple-actions-in-effects.md This example shows the preferred approach of dispatching a single action and handling subsequent logic based on that action. ```ts // in effect: export class Effects { loadEmployeeList$ = createEffect(() => { return this.actions$.pipe( ofType(componentLoaded), exhaustMap(() => this.dataService.loadEmployeeList().pipe( map((response) => loadEmployeeListSuccess(response)), catchError((error) => loadEmployeeListError(error)) ) ) ); }); // use the one dispatched action loadCompanyList$ = createEffect(() => { return this.actions$.pipe( ofType(loadEmployeeListSuccess) // handle loadCompanyList ); }); //use the one dispatched action cleanData$ = createEffect(() => { return this.actions$.pipe( ofType(loadEmployeeListSuccess) // handle cleanData ); }); constructor(private readonly actions$: Actions) {} } ``` -------------------------------- ### Run All Tests Source: https://github.com/ngrx/platform/blob/main/CONTRIBUTING.md Execute the entire test suite for the project. ```shell pnpm exec test ``` -------------------------------- ### Application Configuration with Router Store Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/router-store/configuration.md Sets up the application configuration, providing the router, store, and router store with a custom serializer. ```typescript import { ApplicationConfig } from '@angular/core'; import { provideRouter } from '@angular/router'; import { provideStore } from '@ngrx/store'; import { provideRouterStore, routerReducer, } from '@ngrx/router-store'; import { AppComponent } from './app.component'; import { CustomSerializer } from './custom-serializer'; export const appConfig: ApplicationConfig = { providers: [ provideRouter([ // routes ]), provideStore({ router: routerReducer, }), provideRouterStore({ serializer: CustomSerializer, }), ], }; ``` -------------------------------- ### Create MockStore with createMockStore Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/testing.md Shows an alternative method to create a MockStore instance using the createMockStore function for testing. This approach simplifies MockStore creation without TestBed. ```typescript import { MockStore, createMockStore } from '@ngrx/store/testing'; describe('Books Component', () => { let store: MockStore; const initialState = { books: ['Book 1', 'Book 2', 'Book 3'] }; beforeEach(() => { store = createMockStore({ initialState }); }); }); ``` -------------------------------- ### StoreModule.forFeature Configuration (After) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v13.md Demonstrates the updated `StoreModule.forFeature` usage, which no longer accepts a configuration object. ```ts StoreModule.forFeature(featureSlice); StoreModule.forFeature({ name: 'feature', reducer: featureReducer }); ``` -------------------------------- ### Implement OnStoreInit in ComponentStore Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/component-store/lifecycle.md Use the OnStoreInit interface to execute logic immediately after the store class is instantiated. ```ts export interface BooksState { collection: Book[]; } export const initialState: BooksState = { collection: [], }; @Injectable() export class BooksStore extends ComponentStore implements OnStoreInit { constructor() { super(initialState); } ngrxOnStoreInit() { // called after store has been instantiated } } ``` ```ts @Component({ // ... other metadata providers: [provideComponentStore(BooksStore)], }) export class BooksPageComponent { constructor(private booksStore: BooksStore) {} } ``` -------------------------------- ### Generate Initial State Management Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/index.md Generates the initial state management files and registers them in the application's root module. Use the --root and --module flags to specify the location. ```sh ng generate @ngrx/schematics:store State --root --module app.module.ts ``` -------------------------------- ### Install NgRx Signals via Angular CLI Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/signals/install.md Use the ng add command to automatically update dependencies and install the package. ```sh ng add @ngrx/signals@latest ``` -------------------------------- ### Example Commit Message: Fix Source: https://github.com/ngrx/platform/blob/main/CONTRIBUTING.md An example commit message for a bug fix, including a description in the body explaining the necessity of the change. ```git fix(release): need to depend on latest rxjs and zone.js The version in our package.json gets copied to the one we publish, and users need the latest of these. ``` -------------------------------- ### StoreModule.forFeature Configuration (Before) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v13.md Shows the previous usage of `StoreModule.forFeature` accepting a configuration object for initialState and metaReducers. ```ts StoreModule.forFeature(featureSlice, { initialState: 100, metaReducers: [metaReducer], }); StoreModule.forFeature( { name: 'feature', reducer: featureReducer }, { initialState: 100, metaReducers: [metaReducer] } ); ``` -------------------------------- ### Install NgRx Entity with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/entity/install.md Use this command to automatically add the NgRx Entity package to your project. It updates `package.json` and runs `npm install`. ```sh ng add @ngrx/entity@latest ``` -------------------------------- ### Install @ngrx/data with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/data/install.md Use this command to automatically install and configure the @ngrx/data package in your Angular project. It handles dependency updates and module imports. ```sh ng add @ngrx/data@latest ``` -------------------------------- ### Generate Store with Custom Path Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/store.md Generate the initial state management files in a specified 'store' folder and register them within the app.module.ts. ```sh ng generate store State --root --state-path store --module app.module.ts ``` -------------------------------- ### Reset Mock Store in Angular Tests (Legacy Setup) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v13.md Provides the `afterEach` hook logic for resetting mock store selectors when using a legacy `test.ts` setup in Angular testing. ```ts import { getTestBed } from '@angular/core/testing'; import { MockStore } from '@ngrx/store/testing'; afterEach(() => { getTestBed().inject(MockStore, null)?.resetSelectors(); }); ``` -------------------------------- ### Register Root State with Standalone API Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/reducers.md Use `provideStore()` to initialize the root state with an empty object when using the Standalone API. ```typescript import { bootstrapApplication } from '@angular/platform-browser'; import { provideStore } from '@ngrx/store'; import { AppComponent } from './app.component'; bootstrapApplication(AppComponent, { providers: [provideStore()], }); ``` -------------------------------- ### Initialize EntityCollectionService and Subscribe to Selectors Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/data/entity-collection-service.md This snippet shows how to create an EntityCollectionService for 'Hero' entities using the EntityCollectionServiceFactory and subscribe to selector observables like filteredEntities$ and loading$. ```typescript constructor(EntityCollectionServiceFactory: EntityCollectionServiceFactory) { this.heroService = EntityCollectionServiceFactory.create('Hero'); this.filteredHeroes$ = this.heroService.filteredEntities$; this.loading$ = this.heroService.loading$; } getHeroes() { this.heroService.getAll(); } add(hero: Hero) { this.heroService.add(hero); } deleteHero(hero: Hero) { this.heroService.delete(hero.id); } update(hero: Hero) { this.heroService.update(hero); } ``` -------------------------------- ### Incorrect usage of signalState Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/signal-state-no-arrays-at-root-level.md Examples of invalid initial states where an array is provided at the root level. ```ts const store = withState([1, 2, 3]); const store = withState([{ foo: 'bar' }]); const store = withState([]); const initialState = []; const store = withState(initialState); ``` -------------------------------- ### Correct usage of type function Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/enforce-type-call.md Examples showing the type function correctly invoked with parentheses. ```ts import { type } from '@ngrx/signals'; const stateType = type<{ count: number }>(); ``` ```ts import { type as typeFn } from '@ngrx/signals'; const stateType = typeFn<{ count: number; name: string }>(); ``` -------------------------------- ### Create EntityAdapter for User Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/entity/interfaces.md Demonstrates how to create an EntityAdapter instance for a specific entity type (User) using createEntityAdapter. This adapter provides methods for managing the entity state. ```typescript export const adapter: EntityAdapter = createEntityAdapter(); ``` -------------------------------- ### Install @ngrx/schematics with ng add Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/install.md Use this command to automatically configure the schematics collection in your angular.json file. ```sh ng add @ngrx/schematics@latest ``` -------------------------------- ### Variadic Tuple Types for createSelector (Before) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v13.md Example showing the previous limitation on the number of child selectors for `createSelector`. ```ts const selector = createSelector< State, Customer, Order[], CustomerWithOrder >; ``` -------------------------------- ### Mock Store Setup and Usage Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/testing.md Sets up a mock store for testing components or guards that depend on NgRx Store. It allows for easy state manipulation and assertion of observable emissions. ```typescript import { TestBed } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { TestScheduler } from 'rxjs/testing'; import { AuthGuard } from '../guards/auth.guard'; describe('Auth Guard', () => { let guard: AuthGuard; let store: MockStore; let testScheduler: TestScheduler; const initialState = { loggedIn: false }; beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => { expect(actual).toEqual(expected); }); TestBed.configureTestingModule({ imports: [ // any modules needed ], providers: [ AuthGuard, provideMockStore({ initialState }), // other providers ], }); store = TestBed.inject(MockStore); guard = TestBed.inject(AuthGuard); }); it('should return false if the user state is not logged in', () => { testScheduler.run(({ expectObservable }) => { expectObservable(guard.canActivate()).toBe('(a|)', { a: false }); }); }); it('should return true if the user state is logged in', () => { store.setState({ loggedIn: true }); testScheduler.run(({ expectObservable }) => { expectObservable(guard.canActivate()).toBe('(a|)', { a: true }); }); }); }); ``` -------------------------------- ### Integrate custom feature into a store Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/signals/signal-store/custom-store-features.md Example of applying the custom feature and updaters within a signalStore definition. ```ts import { inject } from '@angular/core'; import { patchState, signalStore, withMethods } from '@ngrx/signals'; import { setAllEntities, withEntities } from '@ngrx/signals/entities'; import { setFulfilled, setPending, withRequestStatus, } from './with-request-status'; import { BooksService } from './books-service'; import { Book } from './book'; export const BooksStore = signalStore( withEntities(), withRequestStatus(), withMethods((store, booksService = inject(BooksService)) => ({ async loadAll() { patchState(store, setPending()); const books = await booksService.getAll(); patchState(store, setAllEntities(books), setFulfilled()); }, })) ); ``` -------------------------------- ### Listen to ROOT_EFFECTS_INIT Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/effects/lifecycle.md Use the ROOT_EFFECTS_INIT action to execute logic after all root effects have been initialized. ```typescript init$ = createEffect(() => { return this.actions$.pipe( ofType(ROOT_EFFECTS_INIT), map(action => ...) ); }); ``` -------------------------------- ### Configure Store Devtools in environment.ts Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store-devtools/recipes/exclude.md Place the `provideStoreDevtools` configuration in your `environment.ts` file. This ensures it's only included in non-production builds. ```typescript import { provideStoreDevtools } from '@ngrx/store-devtools'; export const environment = { production: false, providers: [provideStoreDevtools({ maxAge: 25 })], }; ``` -------------------------------- ### Correct Signal Store Feature Definitions Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/signal-store-feature-should-use-generic-type.md Examples of feature definitions that correctly implement generic types. ```ts const withY = () => signalStoreFeature({ state: type<{ y: Y }>() }, withState({})); ``` ```ts const withY = <_>() => { return signalStoreFeature( type<{ state: { y: number } }>(), withState({}) ); }; ``` ```ts function withY<_>() { return signalStoreFeature( { state: type<{ y: Y }>() }, withState({}) ); } ``` -------------------------------- ### Replace getMockStore with createMockStore (After) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v16.md Shows the replacement of `getMockStore` with `createMockStore` in v16 for creating mock stores. An automatic migration renames the function. ```ts import { createMockStore } from '@ngrx/store/testing'; const mockStore = createMockStore(); ``` -------------------------------- ### Generate Initial Effects Management Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/schematics/index.md Generates the root effects files and registers them in the application's root module. Use the --root and --module flags to specify the location. ```sh ng generate @ngrx/schematics:effect App --root --module app.module.ts ``` -------------------------------- ### Correct state slice key naming Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/no-reducer-in-key-names.md Examples of compliant key names that omit the word 'reducer'. ```ts StoreModule.forRoot({ customers: customersReducer, }); StoreModule.forFeature({ customers: customersReducer, }); export const reducers: ActionReducerMap = { customers: fromCustomers.reducer, }; ``` -------------------------------- ### Correct Usage of withState Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/with-state-no-arrays-at-root-level.md Demonstrates valid ways to use `withState` with record types or factory functions returning records. ```typescript const store = signalStore(withState({ count: 0 })); ``` ```typescript const store = signalStore(withState({ items: [] })); ``` ```typescript const initialState = { count: 0 }; const store = signalStore(withState(initialState)); ``` ```typescript // Factory function - return type is checked const store = signalStore(withState(() => ({ count: 0 }))); ``` ```typescript // Factory function with dependency injection const INITIAL_STATE = new InjectionToken('InitialState', { factory: () => ({ count: 0 }), }); const store = signalStore(withState(() => inject(INITIAL_STATE))); ``` -------------------------------- ### Incorrect Effect Implementation Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/no-multiple-actions-in-effects.md This example demonstrates an Effect returning an array of multiple actions, which violates the rule. ```ts export class Effects { loadEmployeeList$ = createEffect(() => { return this.actions$.pipe( ofType(componentLoaded), exhaustMap(() => this.dataService.loadEmployeeList().pipe( switchMap((response) => [ loadEmployeeListSuccess(response), loadCompanyList(), cleanData(), ]), catchError((error) => loadEmployeeListError(error)) ) ) ); }); loadCompanyList$ = createEffect(() => { return this.actions$.pipe( ofType(loadCompanyList) // handle loadCompanyList ); }); cleanData$ = createEffect(() => { return this.actions$.pipe( ofType(cleanData) // handle cleanData ); }); constructor(private readonly actions$: Actions) {} } ``` -------------------------------- ### Configure Store Providers Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/store/walkthrough.md Registers the global store and HTTP client in the application configuration. ```typescript import { ApplicationConfig } from '@angular/core'; import { provideStore } from '@ngrx/store'; import { booksReducer } from './state/books.reducer'; import { collectionReducer } from './state/collection.reducer'; import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { providers: [ provideStore({ books: booksReducer, collection: collectionReducer }), provideHttpClient(), ], }; ``` -------------------------------- ### Incorrect usage of type function Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/enforce-type-call.md Examples showing the type function being used without invocation parentheses. ```ts import { type } from '@ngrx/signals'; const stateType = type<{ count: number }>; ``` ```ts import { type as typeFn } from '@ngrx/signals'; const stateType = typeFn<{ count: number }>; ``` -------------------------------- ### Fetch movies in a component Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/effects/index.md Example of a component directly managing state and side effects by subscribing to a service. ```ts import { Component, inject, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; @Component({ template: `
  • {{ movie.name }}
  • `, imports: [CommonModule], }) export class MoviesPageComponent implements OnInit { private moviesService = inject(MoviesService); protected movies: Movie[] = []; ngOnInit() { this.movieService .getAll() .subscribe((movies) => (this.movies = movies)); } } ``` -------------------------------- ### Migrate getMockStore to createMockStore Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v15.md Replaces the deprecated getMockStore testing utility with createMockStore. ```ts import { getMockStore } from '@ngrx/store/testing'; const mockStore = getMockStore(); ``` ```ts import { createMockStore } from '@ngrx/store/testing'; const mockStore = createMockStore(); ``` -------------------------------- ### Load All Books with rxMethod (No Arguments) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/signals/rxjs-integration.md Define a reactive method without arguments using `rxMethod` to fetch all books. The `exhaustMap` operator ensures that only the latest request is processed. `tapResponse` is used for handling the API response. ```typescript import { Component, inject, signal } from '@angular/core'; import { exhaustMap } from 'rxjs'; import { rxMethod } from '@ngrx/signals/rxjs-interop'; import { tapResponse } from '@ngrx/operators'; import { BooksService } from './books-service'; import { Book } from './book'; @Component({ /* ... */ }) export class BookList { readonly #booksService = inject(BooksService); readonly books = signal([]); // 👇 Creating a reactive method without arguments. readonly loadAllBooks = rxMethod( exhaustMap(() => { return this.#booksService.getAll().pipe( tapResponse({ next: (books) => this.books.set(books), error: console.error, }) ); }) ); constructor() { this.loadAllBooks(); } } ``` -------------------------------- ### Initialize ComponentStore via constructor Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/component-store/initialization.md Sets the initial state immediately upon class instantiation by calling super with the initial state object. ```ts export interface MoviesState { movies: Movie[]; } @Injectable() export class MoviesStore extends ComponentStore { constructor() { super({ movies: [] }); } } ``` -------------------------------- ### SignalStore with Initial State Factory Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/signals/signal-store/index.md Demonstrates creating a SignalStore where the initial state is provided by a factory function, allowing for dependency injection of initial state values. ```typescript import { inject, InjectionToken } from '@angular/core'; import { signalStore, withState } from '@ngrx/signals'; import { Book } from './book'; type BookSearchState = { books: Book[]; isLoading: boolean; filter: { query: string; order: 'asc' | 'desc' }; }; const initialState: BookSearchState = { books: [], isLoading: false, filter: { query: '', order: 'asc' }, }; const BOOK_SEARCH_STATE = new InjectionToken( 'BookSearchState', { factory: () => initialState } ); const BookSearchStore = signalStore( withState(() => inject(BOOK_SEARCH_STATE)) ); ``` -------------------------------- ### Action Creator Props (Before) Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/migration/v13.md Example of an action created with `createAction` using a primitive type for props, which is no longer allowed. ```ts const action = createAction('[Source] Event', props()); ``` -------------------------------- ### Incorrect Usage of withState Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/with-state-no-arrays-at-root-level.md Shows examples of `withState` being used with forbidden non-record types or factory functions returning them. ```typescript const store = signalStore(withState([1, 2, 3])); ``` ```typescript const store = signalStore(withState(new Set())); ``` ```typescript const store = signalStore(withState(new Map())); ``` ```typescript const initialState: number[] = []; const store = signalStore(withState(initialState)); ``` ```typescript // Factory function returning a forbidden type const store = signalStore(withState(() => [1, 2, 3])); ``` -------------------------------- ### Correct: Dispatching a Single Combining Action Source: https://github.com/ngrx/platform/blob/main/projects/www/src/app/pages/guide/eslint-plugin/rules/avoid-dispatching-multiple-actions-sequentially.md This example demonstrates the correct approach by dispatching a single `componentLoaded` action. Subsequent effects then handle the loading of employee lists, company lists, and data cleaning, abstracting the details from the component. ```typescript // in component code: export class Component implements OnInit { constructor( private readonly store: Store, ) {} ngOnInit() { this.store.dispatch(componentLoaded()); } } // in effect: export class Effects { loadEmployeeList$ = createEffect(() => this.actions.pipe( ofType(componentLoaded), exhaustMap(() => this.dataService.loadEmployeeList().pipe( map(response => loadEmployeeListSuccess(response)), catchError(error => loadEmployeeListError(error)), )), )); loadCompanyList$ = createEffect(() => this.actions.pipe( ofType(componentLoaded), // handle loadCompanyList )); cleanData$ = createEffect(() => this.actions.pipe( ofType(componentLoaded), // handle cleanData )); constructor( private readonly actions$: Actions, ) {} } ```