Angular 6 NgRx Store example – Angular State Management

NgRx Store is a state management solution for Angular apps that helps us build applications by working around our app’s data (state). In this tutorial, we’re gonna look at how to work with NgRx Store, custom Actions, Reducers. Then we will practice to understand all of them in a simple practical Angular 6 example.

Related Posts:
Angular 6 Search Box example with Youtube API & RxJS 6
– NGXS: Angular 6 NGXS example – Angular State Management
– State Management with Redux: Introduction to Redux – a simple practical Redux example

– Reactive Streams:

NgRx Store to manage App State

Why we need a State container

State container helps JavaScript applications to manage state.
=> Whenever we wanna read the state, look into only one single place – NgRx Store.
=> Managing the state could be simplified by dealing with simple objects and pure functions.

NgRx Store

Store holds the current state so that we can see it as a single source of truth for our data.
– access state using store.select(property) (property is defined at app.module.ts in StoreModule.forRoot()).
– update state via store.dispatch(action).


export interface AppState {
    readonly customer: Customer[];
}

// component
import { Store } from '@ngrx/store';
import { AppState } from '../../app.state';

export class MyComponent {

  customers: Observable;

  constructor(private store: Store) {
    this.customers = store.select('customer');
  }

  saveCustomer(data) {
    this.store.dispatch(new ActionCreateCustomer({data}));
  }
}

Action

Action is payload of information that is sent to Store using store.dispatch(action).
Action must have a type property that should typically be defined as string constants. It indicates the type of action being performed:


import { Action } from '@ngrx/store';

export const CREATE_CUSTOMER = 'Customer_Create';
export const DELETE_CUSTOMER = 'Customer_Delete';

export class CreateCustomer implements Action {
    readonly type = CREATE_CUSTOMER;

    constructor(public payload: Customer) { }
}

export class DeleteCustomer implements Action {
    readonly type = DELETE_CUSTOMER;

    constructor(public id: string) { }
}

export type Actions = CreateCustomer | DeleteCustomer;

Reducer

Reducer is a pure function that generates a new state based on an Action it receives. These Actions only describe what happened, but don’t describe how state changes.


export function reducer(
    state: Customer[] = [initialState],
    action: Actions) {

    switch (action.type) {
        case CREATE_CUSTOMER:
            return [...state, action.payload];

        case DELETE_CUSTOMER:
            return state.filter(({ id }) => id !== action.id);

        default:
            return state;
    }
}

*Note: Reducer must be a pure function:
=> From given arguments, just calculate the next state and return it.
=> No side effects. No API or non-pure function calls. No mutations.

Import @ngrx/store and Reducer

app.module.ts


import { StoreModule } from '@ngrx/store';
import { reducer } from './reducers/customer.reducer';

@NgModule({
  declarations: [ ... ],
  imports: [
    ...
    StoreModule.forRoot({
      customer: reducer
    })
  ],
  ...
})
export class AppModule { }

Practice

Example overview

angular-6-ngrx-store-example-project-structure

This is a simple Angular 6 with NgRx Store Application that has:
AppState (app.state.ts) as the main state that is stored inside NgRx Store.
– 2 types of Action: CREATE_CUSTOMER and DELETE_CUSTOMER (customer.actions.ts).
– One Reducer (customer.reducer.ts).

We can save/remove Customer. App will update UI immediately.

angular-6-ngrx-store-example-result

>> Click on Delete button from any Customer:

angular-6-ngrx-store-example-delete-result

Step by step

Install NgRx Store

Run cmd: npm install @ngrx/store.

Create Data Model

app/customers/models/customer.ts


export class Customer {
    id: string;
    name: string;
    age: number;
    active: boolean;

    constructor(id?: string, name?: string, age?: number, active?: boolean) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.active = active;
    }
}
Create Actions

app/actions/customer.actions.ts


import { Injectable } from '@angular/core';
import { Action } from '@ngrx/store';
import { Customer } from '../customers/models/customer';

export const CREATE_CUSTOMER = 'Customer_Create';
export const DELETE_CUSTOMER = 'Customer_Delete';

export class CreateCustomer implements Action {
    readonly type = CREATE_CUSTOMER;

    constructor(public payload: Customer) { }
}

export class DeleteCustomer implements Action {
    readonly type = DELETE_CUSTOMER;

    constructor(public id: string) { }
}

export type Actions = CreateCustomer | DeleteCustomer;
Create Reducer

app/reducers/customer.reducer.ts


import { Customer } from '../customers/models/customer';
import { Actions, CREATE_CUSTOMER, DELETE_CUSTOMER } from '../actions/customer.actions';

const initialState: Customer = {
    id: '1',
    name: 'Andrien',
    age: 27,
    active: true
};

export function reducer(
    state: Customer[] = [initialState],
    action: Actions) {

    switch (action.type) {
        case CREATE_CUSTOMER:
            return [...state, action.payload];

        case DELETE_CUSTOMER:
            return state.filter(({ id }) => id !== action.id);

        default:
            return state;
    }
}
Create App State

app/app.state.ts


import { Customer } from './customers/models/customer';

export interface AppState {
    readonly customer: Customer[];
}
Import NgRx Store

app/app.module.ts


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

import { StoreModule } from '@ngrx/store';
import { reducer } from './reducers/customer.reducer';

import { AppComponent } from './app.component';
import { CreateCustomerComponent } from './customers/create-customer/create-customer.component';
import { CustomersListComponent } from './customers/customers-list/customers-list.component';
import { CustomerDetailsComponent } from './customers/customer-details/customer-details.component';

@NgModule({
  declarations: [
    AppComponent,
    CreateCustomerComponent,
    CustomersListComponent,
    CustomerDetailsComponent
  ],
  imports: [
    BrowserModule,
    StoreModule.forRoot({
      customer: reducer
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Create Components
Create Customer Component

customers/create-customer/create-customer.component.ts


import { Component, OnInit } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '../../app.state';
import { CreateCustomer } from '../../actions/customer.actions';

@Component({
  selector: 'app-create-customer',
  templateUrl: './create-customer.component.html',
  styleUrls: ['./create-customer.component.css']
})
export class CreateCustomerComponent implements OnInit {

  constructor(private store: Store) { }

  ngOnInit() {
  }

  saveCustomer(id, name, age) {
    this.store.dispatch(new CreateCustomer(
      {
        id: id,
        name: name,
        age: age,
        active: false
      }
    ));
  }
}

customers/create-customer/create-customer.component.html

<div style="max-width:300px;">
  <h3>Create Customers</h3>
  <div class="form-group">
    <input class="form-control" type="text" placeholder="id" #id>
  </div>
  <div class="form-group">
    <input class="form-control" type="text" placeholder="name" #name>
  </div>
  <div class="form-group">
    <input class="form-control" type="number" placeholder="age" #age>
  </div>
  <button class="btn btn-success" (click)="saveCustomer(id.value,name.value,age.value)">Save Customer</button>
</div>
Customer Details Component

customers/customer-details/customer-details.component.ts


import { Component, OnInit, Input } from '@angular/core';
import { Customer } from '../models/customer';
import { Store } from '@ngrx/store';
import { AppState } from '../../app.state';
import { DeleteCustomer } from '../../actions/customer.actions';

@Component({
  selector: 'app-customer-details',
  templateUrl: './customer-details.component.html',
  styleUrls: ['./customer-details.component.css']
})
export class CustomerDetailsComponent implements OnInit {

  @Input() customer: Customer;

  constructor(private store: Store) { }

  ngOnInit() {
  }

  removeCustomer(id) {
    this.store.dispatch(new DeleteCustomer(id));
  }
}

customers/customer-details/customer-details.component.html

<div *ngIf="customer">
	<div>
		<label>Name: </label> {{customer.name}}
	</div>
	<div>
		<label>Age: </label> {{customer.age}}
	</div>
	<span class="button is-small btn-danger" (click)='removeCustomer(customer.id)'>Delete</span>
 	<hr/>
</div>
Customers List Component

customers/customers-list/customers-list.component.ts


import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { Store } from '@ngrx/store';

import { Customer } from '../models/customer';
import { AppState } from '../../app.state';

@Component({
  selector: 'app-customers-list',
  templateUrl: './customers-list.component.html',
  styleUrls: ['./customers-list.component.css']
})
export class CustomersListComponent implements OnInit {

  customers: Observable;

  constructor(private store: Store) {
    this.customers = store.select('customer');
  }

  ngOnInit() {
  }

}

customers/customers-list/customers-list.component.html

<div *ngIf="customers">
  <h3>Customers</h3>
  <div *ngFor="let customer of customers | async">
    <app-customer-details [customer]='customer'></app-customer-details>
  </div>
</div>
Import Components to App Component

app/app.component.ts


import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'ozenero';
  description = 'NgRx Example';
}

app/app.component.html

<div class="container">
    <div style="color: blue;">
        <h1>{{title}}</h1>
        <h3>{{description}}</h3>
    </div>
    <div class="row">
        <div class="col-sm-4">
            <app-create-customer></app-create-customer>
        </div>
        <div class="col-sm-4">
            <app-customers-list></app-customers-list>
        </div>
    </div>
</div>

Source Code

Angular6-NgRx-Example

92 thoughts on “Angular 6 NgRx Store example – Angular State Management”

  1. Hi! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me.
    Anyways, I’m definitely happy I found it and
    I’ll be bookmarking and checking back often!

  2. We stumbled over here by a different web page and thought I should check things out.
    I like what I see so i am just following you. Look forward to going
    over your web page for a second time.

  3. Do you mind if I quote a few of your articles as long as I provide credit
    and sources back to your site? My website is in the very same area of interest as
    yours and my users would truly benefit from some of the
    information you provide here. Please let me know if this alright with you.
    Appreciate it!

  4. Hello, Neat post. There’s an issue together with your site in internet explorer, could check this?
    IE nonetheless is the market leader and a good section of folks will omit your
    wonderful writing because of this problem.

  5. My spouѕe ɑnd I stumƅled over here coning from a different web adxdress and thought I
    may as well check thiings out. І liқ what I see so now i’m following
    you. Look forwarԀ to checking out your web page again.

  6. Hi, I do think this is an excellent blog. I stumbledupon it 😉 I will revisit once
    again since i have bookmarked it. Money and freedom is the greatest way to change, may you be
    rich and continue to guide other people.

  7. Hi there! This is kind of off topic but I need some help from an established blog.
    Is it very difficult to set up your own blog?
    I’m not very techincal but I can figure things out pretty quick.
    I’m thinking about creating my own but I’m not sure where to start.
    Do you have any ideas or suggestions? Many thanks

  8. I have been exploring for a little for any high-quality articles or weblog
    posts on this kind of house . Exploring in Yahoo I at last stumbled
    upon this site. Reading this info So i’m satisfied
    to show that I have an incredibly just right uncanny feeling I came upon exactly what I needed.
    I such a lot certainly will make sure to do not disregard this web site
    and give it a look on a relentless basis.

  9. Hi, I do think this is an excellent blog. I stumbledupon it 😉 I may revisit once again since
    i have bookmarked it. Money and freedom is the greatest way to change, may you be rich and continue to guide other people.

  10. Definitely imagine that that you stated. Your favourite justification appeared to be on the web the simplest thing to take
    note of. I say to you, I definitely get annoyed even as people think
    about worries that they just don’t recognise about.
    You controlled to hit the nail upon the highest and also outlined out
    the entire thing without having side-effects , other folks could take a signal.
    Will likely be again to get more. Thank you

  11. Hello there! This blog post couldn’t be written much better!
    Looking at this post reminds me of my previous roommate! He always kept preaching about this.
    I most certainly will send this article to him. Pretty sure
    he’ll have a great read. Thank you for sharing!

  12. It’s perfect time to make some plans for the future and it’s time to be happy.

    I’ve read this post and if I could I want to suggest you few interesting things or advice.
    Maybe you can write next articles referring to this article.

    I desire to read even more things about it!

  13. Heya just wanted to give you a quick heads up and let you know a few
    of the pictures aren’t loading properly. I’m not sure why but I think
    its a linking issue. I’ve tried it in two different internet browsers and both show the
    same outcome.

  14. I just like tһe hellpful info you provide on your articles.
    I’ll bookmark your ᴡeblog and check ⲟnbcе morе right hee regularly.
    I’m qᥙite certain I ᴡill be tolҝd many new stjff right here!
    Best off luck for tһe folⅼowing!

  15. Greetings! This is my first comment here so I just wanted to give a quick shout out and say I really enjoy reading your blog posts.

    Can you recommend any other blogs/websites/forums that go over the
    same subjects? Appreciate it!

  16. What i don’t realize is in truth how you are no longer really a lot more
    smartly-preferred than you might be right now.
    You are so intelligent. You know thus considerably relating to this subject, made
    me individually imagine it from so many varied angles. Its like women and men don’t seem to be involved except it’s
    something to do with Girl gaga! Your personal stuffs excellent.
    All the time care for it up!

  17. Woah! I’m really digging the template/theme of this blog.
    It’s simple, yet effective. A lot of times it’s difficult
    to get that “perfect balance” between user friendliness and visual appeal.
    I must say you’ve done a amazing job with this.
    Also, the blog loads very quick for me on Internet explorer.
    Excellent Blog!

  18. Нi, I think your ѕite might be having browser compatibility issues.
    When I lօok at yߋur website in Operɑ, it looks fiјe but when ߋpеnikng in Internet Explorer, itt has some
    overlappіng. I just wanted to give you a quick heads up!

    Other then that, wonderful bloɡ!

  19. Ꮐoоɗ dɑy! Thiѕ is kind of off topic but I need some
    help frⲟm ann estɑblished bloɡ. Is it difficult to set up your own bloց?

    I’m not veгy techincal but I can figᥙre things out ρrett quick.
    I’m thinking about making my oown ƅut I’m not suгe where to begin. Do you have any
    ideas or suggestions? With thanks

  20. Нeya! I realizе this is ҝnd of off-toρic however I needed to ask.
    Does building a well-established blog such aas yours take a large amolunt of work?

    I’m bгand new to operatinng a blog but I ddo writе in my disry every day.
    I’d like to staгt a blog so I can share my own experience and thoughts
    onlіne. Please let me know if you have any kind of ideas or tips for new aspiring blog owners.
    Appreciate it!

  21. Hello there! I know this is kinda off topic however I’d
    figured I’d ask. Would you be interested in trading links or
    maybe guest writing a blog post or vice-versa? My site covers a lot of the same subjects
    as yours and I feel we could greatly benefit from each other.
    If you’re interested feel free to send me an e-mail.
    I look forward to hearing from you! Excellent blog by the way!

  22. If some one wants expert view about blogging and site-building afterward i propose him/her to
    pay a visit this blog, Keep up the nice job.

  23. I needed to thank you for this fantastic read!!

    I absolutely enjoyed every little bit of it. I have got you saved as a favorite to check out new stuff you post…

  24. I am sure this piece of writing has touched all the internet viewers, its really
    really good piece of writing on building up new web site.

  25. Wһat’s Going down i’m new to this, I stumblewd upon this I һave
    found It positivеoy usefvul and it has helped me out loads.

    I hopе tto contribute & aѕsist other users lie its aided
    me. Good job.

  26. I think that what you typed made a ton of sense.
    But, what about this? what if you added a little information? I am
    not saying your content is not good., however suppose you
    added a post title to maybe get a person’s attention? I mean ozenero | Mobile & Web Programming Tutorials is a little plain. You might peek at Yahoo’s front page and
    see how they create news headlines to get viewers interested.
    You might try adding a video or a pic or two to get people excited
    about everything’ve written. Just my opinion, it might
    make your website a little bit more interesting.

  27. I was curious if you ever thought of changing the structure of your site?
    Its very well written; I love what youve got to say.
    But maybe you could a little more in the way of content so people could connect with it better.

    Youve got an awful lot of text for only having one or two images.
    Maybe you could space it out better?

  28. Appreciating the time and effort you put into your site and detailed information you present.
    It’s good to come across a blog every once in a while
    that isn’t the same old rehashed material. Fantastic read!

    I’ve saved your site and I’m including your RSS feeds to my Google account.

  29. I do not know whether it’s just me or if everybody else encountering issues with your website.
    It appears like some of the written text within your posts are running off the screen. Can somebody else please provide feedback
    and let me know if this is happening to them as well?
    This may be a problem with my internet browser because I’ve had this happen previously.
    Many thanks

  30. You could definitely see your skills in the work you write.
    The arena hopes for more passionate writers like you who are not afraid to mention how they believe.
    Always go after your heart.

  31. you’re in reality a good webmaster. The site loading velocity is incredible.
    It kind of feels that you are doing any distinctive trick. Moreover, The contents are masterpiece.
    you’ve performed a magnificent task in this matter!

  32. Very good blog! Do you have any suggestions for aspiring writers?
    I’m planning to start my own website soon but I’m a little lost on everything.
    Would you propose starting with a free platform
    like WordPress or go for a paid option? There are
    so many choices out there that I’m totally overwhelmed ..
    Any recommendations? Cheers!

  33. Hello, I think your site might be having
    browser compatibility issues. When I look at your website in Firefox,
    it looks fine but when opening in Internet Explorer, it has some overlapping.

    I just wanted to give you a quick heads up! Other then that,
    awesome blog!

  34. I really like your blog.. very nice colors & theme.
    Did you design this website yourself or did you hire someone to do it for you?
    Plz reply as I’m looking to construct my own blog and
    would like to know where u got this from. thanks
    a lot

  35. I loved as much as you will receive carried out right here.

    The sketch is attractive, your authored subject matter stylish.
    nonetheless, you command get bought an impatience over that you wish be
    delivering the following. unwell unquestionably come further formerly again as exactly the same nearly very often inside case you shield
    this hike.

Leave a Reply

Your email address will not be published. Required fields are marked *