Recognized by Clutch.co as a top-rated Mobile App Development Company.
folio3-mobile
US 408 365 4638
START YOUR PROJECT
  • Solutions
    • Apps Discovery Services
    • Team Augmentation
    • Enterprise
    • AR/VR
    • IoT
    • Wearables
    • Field Sales
    • On Demand Apps
  • Industries
    • Retail
    • Agriculture
    • Healthcare
    • Pharmaceutical & Life Sciences
    • Manufacturing
    • Automotive
    • Logistics
    • Education
  • Technologies
    • Native Mobile Apps
      • iOS
      • Android
    • Cross Platform Apps
      • React Native
      • Flutter
      • Ionic
      • Xamarin
      • NativeScript
      • Sencha
  • Portfolio
  • Blog
  • Contact Us
  • Solutions
    • Apps Discovery Services
    • Team Augmentation
    • Enterprise
    • AR/VR
    • IoT
    • Wearables
    • Field Sales
    • On Demand Apps
  • Industries
    • Retail
    • Agriculture
    • Healthcare
    • Pharmaceutical & Life Sciences
    • Manufacturing
    • Automotive
    • Logistics
    • Education
  • Technologies
    • Native Mobile Apps
      • iOS
      • Android
    • Cross Platform Apps
      • React Native
      • Flutter
      • Ionic
      • Xamarin
      • NativeScript
      • Sencha
  • Portfolio
  • Blog
  • Contact Us

Getting started with NgRx

Published by: Noc Folio3 | June 24, 2022
SCROLL AND BE AMAZED!
Home > Blog > Getting started with NgRx

What is NgRx

Before getting to know NgRx we need to know about Redux, Redux is a design pattern that encapsulates all application data in a single javascript object, providing a consistent global data state at all times, this method is most used in react apps but it can also be applied to angular apps with a library called NgRx which uses Redux core principles with RxJs library under the hood. In this article, we are gonna cover the basics of Redux and then we’ll create an angular app from scratch using NgRx. Let’s start by looking at the core principles of Redux.

Key concepts

  • Actions
  • Reducers
  • Selectors
  • Store

Actions:

So we have a user interface that is displaying some data. Then the user performs an action that will change the state of the data in redux. The only way to change the state is by dispatching an action.

Reducers

Once an action has been dispatched then this action will be used by a reducer function which will copy the current state of the application along with any data changes to a new javascript object. It’s very essential to know that the state is immutable, meaning it can’t be changed directly; it has to be copied over to a whole brand new state. The reason for this is that it provides a predictable tree of state changes that can be used to debug an application, which is Redux’s primary benefit.

Store

Once the reducer has created the new state, it is saved in a data store..

In NgRx we treat this data store as an observable so we can subscribe to it from anywhere in the application This means that all of our components and services will be sharing the same data at any given point in time.

Selector

Selector function pick the desired piece of data from store and reflect the data on the UI

Now let’s start building a brand new NgRx app. The app will add/remove an article and the article will contain only id, title and its content. Following will be the article.interface.ts file we will be using in our app.

article.interface.ts

export interface Article {
  id: number;
  title: string;
  content: string;
}

Create a new Angular application

ng new NgRxApp

Then install NgRx Store

npm install @ngrx/store --save

Create a new file named article.actions.ts in which we will list out action-functions with required props(arguments). The actions are add and remove, first import createAction from ngrx store, create action takes the action argument and props.

article.actions.ts

import { createAction, props } from '@ngrx/store';
import { Article } from '../models/article.interface';
export const ADD_ACTION = '[Article Component] Add';
export const REMOVE_ACTION = '[Article Component] Remove';
export const addArticle = createAction(ADD_ACTION, props<{ article: Article }>());
export const removeArticle = createAction(REMOVE_ACTION, props<{ id: number }>());

Create a new file named article.reducer.ts, then define a reducer function to handle changes in article state based on provided value, first import createReducer from ngrx store, in reducer we will handle the add action by appending article collection with new article, then handle remove action by filtering out the article with its id. In the reducer function, return two properties, one in which we return the previous state like this …state and second one will contain a modified state.

For example:

  on(addArticle, (state, { article }) => {
    return {
// copying previous state
      ...state,
// create new state by appending newly created article obj in article array
      articles: [...state.articles, article]
    };
  }),

article.reducer.ts

import { createReducer, on } from '@ngrx/store';
import { Article } from '../models/article.interface';
import { addArticle, removeArticle } from './article.actions';
 
export const initialState: {articles: ReadonlyArray<Article>} = { articles: []};
 
export const articleReducer = createReducer(
  initialState,
  on(addArticle, (state, { article }) => {
    return {
      ...state,
      articles: [...state.articles, article]
    };
  }),
  on(removeArticle, (state, { id }) => {
    return {
      ...state,
      articles: state.articles.filter((article) => article.id !== id)
    };
  }),
);

Create a new file named article.selector.ts, now, to make sure we get the right data from the store. createFeatureSelector  function for getting the piece of data from the store in this case its articles. Now use createSelector to return articles array.

article.selector.ts

import { createSelector, createFeatureSelector } from '@ngrx/store';
import { Article } from '../models/article.interface';
 
export const selectArticles = 
createFeatureSelector<{articles: ReadonlyArray<Article>}>('articles');
 
export const selectArticlesCollection = createSelector(
  selectArticles,
  (state) => state.articles
);

Now that we are done with essential parts to build our app, let’s create a component named article in which we will add and remove the article.

Let’s register our reducer in StoreModule in app.module.ts

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StoreModule } from '@ngrx/store';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { articleReducer } from './article/store/article.reducer';
import { ArticlesComponent } from './article/components/articles/articles.component';
import { ReactiveFormsModule } from '@angular/forms';
 
@NgModule({
  declarations: [
    AppComponent,
    ArticlesComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    ReactiveFormsModule,
    StoreModule.forRoot({ articles: articleReducer }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Import store to inject store service in component, we will use the store for dispatching our action and will also gonna use to select articles from the store with our selector function to display on UI,

Property `articles$` is an observable that will always contain the updated articles list from the store,

`store.dispatch` to perform actions to change the state of the app, dispatch function will take action as an argument.

article.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Article } from '../../models/article.interface';
import { addArticle, removeArticle } from '../../store/article.actions';
import { selectArticlesCollection } from '../../store/article.selectors';
 
@Component({
  selector: 'app-articles',
  templateUrl: './articles.component.html',
  styleUrls: ['./articles.component.css']
})
export class ArticlesComponent implements OnInit {
 
  public articles$ = this.store.select(selectArticlesCollection);
 
  public articleForm = this.fb.group({
    title: (['', Validators.required]),
    content: (['', Validators.required])
  });
 
  constructor(private store: Store, private fb: FormBuilder) { }
 
  ngOnInit(): void {}
 
  onAdd() {
    const article: Article = {id: new Date().getTime(), ...this.articleForm.value};
    this.store.dispatch(addArticle({ article }));
    this.articleForm.reset();
  }
 
  onRemove(id: number) {
    this.store.dispatch(removeArticle({ id }));
  }
}

article.component.html

<form [formGroup]="articleForm">
  <h3>Add Article</h3>
  <input [formControlName]="'title'" type="text" placeholder="Title"><br><br>
  <textarea [formControlName]="'content'" cols="30" rows="10" placeholder="Content"></textarea><br><br>
  <button type="submit" (click)="onAdd()" [disabled]="!this.articleForm.valid">Save</button>
</form>
 
<ng-container *ngFor="let item of articles$ | async; let i = index">
  <div>
    <p><b>Article no.</b> {{i +1}}</p>
    <p><b>Title:</b> {{item.title}}</p>
    <p><b>Content:</b> <br>{{item.content}}</p>
    <p><button (click)="onRemove(item.id)">Remove article</button></p>
  </div>
  <hr>
</ng-container>

Application snap:

What’s next?

In the future, we will be exploring NgRx Effects to handle HTTP requests to manage state from data coming from the server, until then… Take care. See you in the next blog.


About Noc Folio3

Newsletter

Search

Archives

  • December 2023
  • April 2023
  • March 2023
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • October 2021
  • September 2021
  • May 2021
  • February 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • October 2019
  • September 2019
  • August 2019
  • July 2019
  • May 2019

Recent Posts

  • Exploring Flutter Navigation: From Basics to Advanced Routes
  • Web UI Test Automation with Pytest-BDD
  • How to fix IOS compass calibration issues
  • Testing Android Applications With Perfect Coverage
  • How to use useRef hook efficiently? – React

Tags

  • android
  • angular-state-management
  • Automation
  • Compass
  • cross-platform
  • css
  • development
  • firebase
  • hooks
  • ios
  • learn-ngrx
  • ngrx-beginner
  • ngrx/store
  • QA
  • react-native
  • reactjs
  • scss
  • stylesheet
  • styling
  • Testing
  • Test Script
  • UI-UX

Newsletter

Newsletter

Post navigation

Previous Secure Mobile App Credentials in React Native
Next Automation testing using Cucumber BDD with Selenium
Schedule an Appointment with our Mobile App Development Expert
Footer Menu
  • Company
    • About Us
    • Portfolio
    • Blog
    • Careers
    • Contact Us
  • Solutions
    • Apps Discovery Services
    • Team Augmentation
    • Enterprise App Development
    • AR/VR Application Development
    • IoT Application Development
    • Wearables Apps Development
    • Field Sales
    • On-Demand Apps Development
  • Technologies
    • iOS
    • Android
    • React Native
    • Flutter
    • Ionic
    • Xamarin
    • NativeScript
    • HTML5
    • Sencha
  • Industries
    • Retail
    • Agriculture
    • Healthcare
    • Pharmaceutical
    • Manufacturing
    • Automotive
    • Logistics
    • Education

US Office

Belmont, California – 1301 Shoreway Road, Suite 160, Belmont, CA 94002

Pleasanton, California – 6701 Koll Center Parkway, #250 Pleasanton, CA 94566

Tel: +1 408 365 4638
Support: +1 (408) 512 1812

Mexico Office

Amado Nervo #2200, Edificio Esfera 1 piso 4, Col. Jardines del Sol, CP. 45050, Zapopan, Jalisco, Mexico

Bulgaria Office

49 Bacho Kiro Street, Sofia, 1000, Bulgaria

Canada Office​

895 Don Mills Road, Two Morneau Shepell Centre, Suite 900, Toronto, Ontario, M3C 1W3, Canada

UK Office

Export House, Cawsey Way, Woking Surrey, GU21 6QX

Tel: +44 (0) 14 8361 6611

UAE Office

Dubai, UAE – Dubai Internet City, 1st Floor, Building Number 12, Premises ED 29, Dubai, UAE

Tel: +971-55-6540154
Tel: +971-04-2505173

Pakistan Office

Folio3 Tower, Plot 26, Block B, SMCH Society, Main Shahrah-e-Faisal, Karachi.

First Floor, Blue Mall 8-R, MM Alam Road Gulberg III, Lahore.

Tel: +92-21-3432 3721-4 

© 2025, Folio3 Software Inc., All rights reserved.

  • Privacy policy and terms of use
  • Cookie Policy
Follow us on
Facebook-f Linkedin-in Instagram

Get a free app audit

[contact-form-7 id="3548" title="Float Banner Form"]