In today’s short tutorial I will show you how to install Ngrx and Angular material in a brand new project, this would be very helpful for new people to understand Ngrx and material is just something additional.

GitHub repo

My follow along repo of Angular Ngrx Course

ng new angular-with-ngrx-tutorial
cd angular-with-ngrx-tutorial
ng add @angular/material

Now install Ngrx packages as well

ng add @ngrx/store
npm install @ngrx/effects
npm install @ngrx/router-store
npm install @ngrx/store-devtools
npm install @ngrx/entity
ng add @ngrx/schematics
npm install --save-dev ngrx-store-freeze

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { StoreModule } from '@ngrx/store';
import { reducers, metaReducers } from './reducers';

import { EffectsModule } from '@ngrx/effects';
import { environment } from 'src/environments/environment';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { StoreRouterConnectingModule } from '@ngrx/router-store';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    StoreModule.forRoot(reducers, {
      metaReducers,
      runtimeChecks: {
        strictStateImmutability: true,
        strictActionImmutability: true
      }
    }),
    EffectsModule.forRoot([]),
    StoreModule.forRoot(reducers, { metaReducers }),
    !environment.production ? StoreDevtoolsModule.instrument() : [],
    StoreRouterConnectingModule.forRoot({ stateKey: 'router' }),
    EffectsModule.forFeature([PeopleEffects])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

By that time you should have reducers folder made automatically with index.ts file in it in there you can put my example of people state.

index.ts

export interface Person {
  name: string;
  age: number;
}

// this is where you put all you different states of ngrx
export interface State {
  people: PeopleState;
}

// and this is one particular state from many
export interface PeopleState {
  people: Person[];
}

export const reducers: ActionReducerMap<State> = {
  people: peopleReducer
};

export const initialPeopleState: PeopleState = {
  people: []
} as PeopleState;

export function peopleReducer(
  state = initialPeopleState,
  action: PeopleActions): AppState {
  switch (action.type) {
    case PeopleActionTypes.LoadPeoplesSuccess:
      return {
        ...state,
        people: action.payload.data
      } as any;
    default:
      return state;
  }
}

Now make foders actions, effects and selectors

ng g action actions/people

Leave it as it is generated it’s okay like that

ng g effect effects/people --module app.module

effects/people.effects.ts

import { Injectable } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { PeopleState, Person } from '../reducers';
import { LoadPeoples, PeopleActionTypes, LoadPeoplesSuccess } from '../actions/people.actions';
import { defer, of, Observable } from 'rxjs';
import { tap } from 'rxjs/operators';



@Injectable()
export class PeopleEffects {



  constructor(
    private actions$: Actions,
    private store: Store<PeopleState>) { }

  @Effect({ dispatch: false })
  logout$ = this.actions$.pipe(
    ofType<LoadPeoples>(PeopleActionTypes.LoadPeoples),
    tap(() => {
      try {
        const people: Person[] = [
          {
            name: 'Maverick',
            age: 26,
          } as Person
        ];
        this.store.dispatch(new LoadPeoplesSuccess({ data: people }));
      } catch (error) {

      }
    })
  );
}

And everything seem to be wired up now let’s show some people in app.component.html

<div *ngFor="let item of people$ | async">
   {{ item.name }} {{ item.age }}
</div>

Also don’t forget to add this to your app.component.ts

import { Observable } from 'rxjs';
import { LoadPeoples } from './actions/people.actions';
import { PeopleState, Person } from './reducers/index';
import { Component, OnInit } from '@angular/core';
import { Store, select } from '@ngrx/store';
import { selectPeople } from './selectors/people.selectors';
import { map } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  people$: Observable<Person[]>;

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

  ngOnInit(): void {
    this.store.dispatch(new LoadPeoples());

    this.people$ = this.store.pipe(
      select(selectPeople)
    );
  }
}

And finally ng serve should show you the people on home page.