diff --git a/src/pages/snippets/component-store-with-global-state.mdx b/src/pages/snippets/component-store-with-global-state.mdx new file mode 100644 index 0000000..34b2e80 --- /dev/null +++ b/src/pages/snippets/component-store-with-global-state.mdx @@ -0,0 +1,137 @@ +--- +title: Global NgRx State and NgRx Component Store +description: "Pull in global state and use in Component Store" +tags: ["angular", "ngrx", "state"] +pubDate: Feb 25, 2023 +contributedBy: "@JayCooperBell" +--- + +An example of a simple global NgRx Store that is used in a ComponentStore that reacts to global state changes and manipulates +the rest. + +Set up a global NgRx Store with Effects. +```typescript +import { createAction, createFeature, createReducer, on } from '@ngrx/store'; +import { createEffect } from '@ngrx/effects'; +import { interval, map } from 'rxjs'; + +interface CounterState { + counter: number; +} + +const initialCounterState: CounterState = { + counter: 0, +}; + +export const incrementCounter = createAction( + '[Angular Snippets Example] Increment Counter' +); + +export const counterState = createFeature({ + name: 'counter', + reducer: createReducer( + initialCounterState, + on(incrementCounter, (state) => ({ + ...state, + counter: state.counter + 1, + })) + ), +}); + +export const { selectCounter } = counterState; + +export const incrementCounterEffect = createEffect( + () => interval(1000).pipe(map(() => incrementCounter())), + { functional: true } +); +``` + +Add your global state to the application +```typescript + + +import { bootstrapApplication } from '@angular/platform-browser'; +import { AppComponent } from './app/app.component'; +import { provideState, provideStore } from '@ngrx/store'; +import { + counterState, + incrementCounterEffect, +} from './app/global-state-in-component-store'; +import { provideEffects } from '@ngrx/effects'; + +bootstrapApplication(AppComponent, { + providers: [ + provideStore({}), + provideState(counterState), + provideEffects({ incrementCounterEffect }), + ], +}).catch((err) => console.error(err)); +``` + +Pull the global state into a component store +```typescript +import { Component, inject, Injectable } from '@angular/core'; +import { ComponentStore } from '@ngrx/component-store'; +import { Store } from '@ngrx/store'; +import { Observable, tap } from 'rxjs'; +import { AsyncPipe } from '@angular/common'; + +interface MyState { + counter: number; +} + +@Injectable({ providedIn: 'root' }) +export class ComponentStoreWithGlobalState extends ComponentStore { + readonly counter$ = this.select((state) => state.counter); + + private readonly store = inject(Store); + + private readonly setCounter = this.updater((state, counter: number) => ({ + ...state, + counter, + })); + + private readonly multiplyGlobalStateByTwo = this.effect( + (origin$: Observable) => + origin$.pipe(tap((counter) => this.setCounter(counter * 2))) + ); + + constructor() { + super({ counter: 0 }); + + this.multiplyGlobalStateByTwo(this.store.select(selectCounter)); + } +} + +@Component({ + selector: 'component-store-with-global-state', + standalone: true, + providers: [ComponentStoreWithGlobalState], + imports: [AsyncPipe], + template: `
{{ counter$ | async }}
`, +}) +export class ComponentStoreWithGlobalStateComponent { + readonly store = inject(ComponentStoreWithGlobalState); + + readonly counter$ = this.store.counter$; +} +``` + +Use the component +```typescript +import { Component } from '@angular/core'; +import { ComponentStoreWithGlobalStateComponent } from './global-state-in-component-store'; + +@Component({ + standalone: true, + selector: 'angular-snippet-examples-root', + template: ` + + `, + styles: [], + imports: [ + ComponentStoreWithGlobalStateComponent, + ], +}) +export class AppComponent {} +```