Skip to content
This repository has been archived by the owner on May 21, 2021. It is now read-only.

ng-sm/query

Repository files navigation

Query module based on the @ngrx/store package.

Installation

yarn add @ngsm/query or npm i @ngsm/query --save

Requirements

Library requires @ngrx/store module.

Usage

State (for example homepage.state.ts):

import { queryReducer } from '@ngsm/query';
import { HomepageApiResponseDto } from 'your-api-dto.interfaces.ts';

export interface HomepageQueryState {
  getHomepageApiQuery?: Query<HomepageApiResponseDto>;
}

export const HOMEPAGE_QUERY_KEY = 'homepageQuery';

export interface HomepagePartialState {
  readonly [HOMEPAGE_QUERY_KEY]: HomepageQueryState;
  // Your feature states, for example:
  // readonly [HOMEPAGE_FEATURE_KEY]: HomepageState;
}

Reducer (for example homepage.reducer.ts):

import { Action } from '@ngrx/store';
import { HomepageQueryState } from './homepage.state';

...

export function homepageQueryReducer(state: HomepageQueryState | undefined, action: Action) {
  return queryReducer(state, action);
}

Selectors (for example homepage.selectors.ts):

import { createFeatureSelector, createSelector } from '@ngrx/store';

export const homepageQueryState = createFeatureSelector<HomepagePartialState, HomepageQueryState>(HOMEPAGE_QUERY_KEY);

export const getHomepageApiQuery = createSelector(
  homepageQueryState,
  (state: HomepageQueryState) => state.getHomepageApiQuery
);

State module (for example homepage-state.module.ts):

import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';

import { HomapageEffects } from './homepage.effects';
import { HomapageFacade } from './homepage.facade';
import { homepageQueryReducer, homepageReducer } from './homepage.reducer';
import { HOMEPAGE_QUERY_KEY } from './homepage.state';

@NgModule({
  imports: [
    StoreModule.forFeature(HOMEPAGE_QUERY_KEY, homepageQueryReducer),
    EffectsModule.forFeature([HomapageEffects]),
  ],
  providers: [HomapageFacade]
})
export class HomapageStateModule {}

Effects (for example homepage.effects.ts):

  ...

  getHomepageApi$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HomepageActions.getHomepageApi),
      mergeMap(() => concat(
        // run inProgress action
        of(QueryActions.inProgress({ query: HomepageQuery.getHomepageApiQuery })),
        this.homepageRepository
          .getHomepageApi()
          .pipe(
            mergeMap((response) => [
              // run success action
              QueryActions.success({ query: HomepageQuery.getHomepageApiQuery, response }),
            ]),
            catchError(error => [
              // run failure action
              QueryActions.failure({ query: HomepageQuery.getHomepageApiQuery, error }),
            ])
          )
      ))
    )
  );

  ...

Facade (for example homepage.facade.ts):

...

@Injectable()
export class HomepageFacade {
  getHomepageQuery$ = this.store.pipe(select(HomepageSelectors.getHomepageQuery));

  loader$ = isQueryInProgress$([
    this.getHomepageQuery$,
    // add all feature queries
    ...,
  ]);

  constructor(private store: Store<HomepagePartialState>) {}

  dispatch(action: Action) {
    this.store.dispatch(action);
  }
}

Author

Sebastian Musiał

kontakt@sebastianmusial.pl

@sebamusial