NGRX: State management in Angular

Knoldus Blog Audio
Reading Time: 5 minutes

Do we require NGRX, state management in each Angular application? Perhaps not generally, so how would we execute state management for board richly applications in which we do require it?

So, for the application state management, NGRX is one of the libraries which helps to manage it.

 It is a Redux execution for Angular. 

The NGRX is an incredible plan for the vast majority of state management necessities. To be sure, it has a touch of standard in examination with different contenders like NGXS, Akita, or plain RxJS. If you want to learn about NGXS, you can refer here.

First, let’s consider the problems first we are going to solve and then we’ll learn about the NGRX and at last, we’ll hop into the coding to create a simple project.

Application State:

First, let’s understand what is application state?  Hypothetically, it is the whole memory of the application, at the same time, it is the information gotten through API calls, client inputs, show UI State, and so forth. A basic solid illustration of utilization state would be a list of employees maintained in an application.

There are several concepts in NGRX which are as follows:

  1. NGRX Store: The store is the thing that holds the application’s state.
  2. Action: An exceptional event occurred through the services and the components which tells how the state should be changed. An example of the action could be like: “ADD_EMPLOYEE”,  “UPDATE_EMPLOYEE”,  “DELETE_EMPLOYEE”.
  3. Reducer: It is the response to every action, based on that, it will create a new unchangeable state and returns to the store. All the changes occur inside the reducer.
  4. Selector: Selector is a function used for getting a piece of the state from the store.
  5. Effect: It is the process that listens for arising every action in an observable, measures the server responses, and returns new actions either immediately or asynchronously to the reducer to change the state.

Interactions between the components are shown in fig:

Now let’s start with basic simple example as below:

  1. With the help of Angular CLI, create an angular application:  
    ng new angular-state-ngrx
    It will create all the files required and install the dependencies.
  2. Install NGRX:
    npm install @ngrx/store –save
    Alternatively, you can run ng add @ngrx/store if you have a CLI 6+ version.  Thus it will be added to the package.json file.
  3. Create the Employee model:
    We’ll create it with the help of angular CLI as like:
    ng g class models/employee
    We can either add it directly to the IDE and the structure will be like src\app\models.
    After that, add the ‘name’ property to it:
export class Employee {
  public name: String = '';
}

4. Add Actions:

Now we’ll add actions to our project. We are going to manage the employee data. We can manipulate the employee’s every state with the help of the actions.

In our project, we’ll use two actions that can affect the state of the employee’s data i.e.;
  1. AddEmployee
  2. DeleteEmployee
     For this, first, we have to create an “employee.actions.ts file” in the src/app folder for the employee actions and the code of the file will be as shown below:
import {Action} from '@ngrx/store';
export enum EmployeeActionTypes {
    Add = '[Employee Component] Add',
    Remove = '[Employee Component] Remove'
}
export class ActionEx implements Action {
    readonly type;
    payload: any;
}
export class EmployeeAdd implements ActionEx {
    readonly type = EmployeeActionTypes.Add;
    constructor(public payload: any) {
    }
}
export class EmployeeRemove implements ActionEx {
    readonly type = EmployeeActionTypes.Remove;
    constructor(public payload: any) {
    }
}

 5) Add an Employee Reducer: 

 Now we should add the reducer; all state changes are going on inside the reducer dependent on the chose ‘Actions.’ If the state is changing, at that point the reducer will make another employee instead of transforming the current employee list. On account of the state change, the reducer is continually going to return a recently created employee list object.

 For this, first, we have to create an “employee.reducers.ts file” in the src/app folder for the employee reducer and the code of the file will be as shown below: 

import {ActionEx, EmployeeActionTypes} from './employee.actions';
export const initialState = [];
export function EmployeeReducer(state = initialState, action: ActionEx) {
  switch (action.type) {
     case EmployeeActionTypes.Add:
         return [...state, action.payload];
     case EmployeeActionTypes.Remove:
         return [
            ...state.slice(0, action.payload),
            ...state.slice(action.payload + 1)
         ];
     default:
        return state;
 }
}

6) Add NGRX Store to the project:
Now let’s add imports into the “app.module.ts” and the store module :
import { StoreModule } from ‘@ngrx/store’;
import { EmployeeReducer } from ‘./employee.reducer’;
Store Module: 
StoreModule.forRoot({ employees: EmployeeReducer })
The  app.module.ts file is as shown below:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { environment } from '../environments/environment';
import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { EmployeeReducer } from './employee.reducer';
import { EmployeeViewComponent } from './employee-view/employee-view.component';
import { EmployeeAddComponent } from './employee-add/employee-add.component';
@NgModule({
  declarations: [
     AppComponent
  ],
  imports: [
     BrowserModule,
     StoreModule.forRoot({ employee: EmployeeReducer }),
     StoreDevtoolsModule.instrument({
      maxAge: 25, // Retains last 25 states
      logOnly: environment.production, // Restrict extension to log-only mode
    }),
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

7) Add an Employee View as a UI Component: 
=> ng g c  EmployeeView

The “employee-view.componet.ts” file includes all the dependencies and it will be like with ’RemoveEmployee’ hook up:
import {Component} from '@angular/core';
import {Employee} from '../models/employee';
import {Observable} from 'rxjs';
import {select, Store} from '@ngrx/store';
import {EmployeeRemove} from '../employee.actions';
@Component({
 selector: 'app-employee-view',
 templateUrl: './employee-view.component.html',
 styleUrls: ['./employee-view.component.css']
})
export class EmployeeViewComponent {
 employee: Observable<Employee[]>;
 constructor(private store: Store<{ employee: Employee[] }>) {
   this.employee = store.pipe(select('employee'));
 }

 removeEmployee(employeeIndex) {
   this.store.dispatch(new EmployeeRemove(employeeIndex));
 }
}

Add the template file code in the “employee-view.component.html” file:

<h4>List of Employee</h4>
<ul class="employee">
 <li *ngFor="let employee of employee | async; let i=index">
   <span >{{i+1}}.</span> {{employee.name}}
   <button style="float: right"     (click)="removeEmployee(i)">Remove</button>
 </li>
</ul>

And apply the CSS as according you need in the “employee-view.component.css” file.

8) Add New Employee as for to add UI Control: 
 ng g c  EmployeeAdd

The code inside the “employee-add.component.ts” file is shown below:

import {Component} from '@angular/core';
import {select, Store} from '@ngrx/store';
import {Employee} from '../models/employee';
import {Observable} from 'rxjs';
import {EmployeeAdd} from '../employee.actions';
@Component({
 selector: 'app-employee-add',
 templateUrl: './employee-add.component.html',
 styleUrls: ['./employee-add.component.css']
})
export class EmployeeAddComponent {
 employee: Observable<Employee[]>;
 constructor(private store: Store<{ employee: Employee[] }>) {
   this.employee = store.pipe(select('employee'));
 }
 AddEmployee(employeeName: string): void {
   const employee = new Employee();
   employee.name = employeeName;
   this.store.dispatch(new EmployeeAdd(employee));
 }
}

And the “employee-add.component.html” file will be like:

<h4>Add New Employee</h4>
<input #box ><button (click)="AddEmployee(box.value)">Add</button>

9) Update the App Component:
Now at last we have to update the “app.component.html” file by removing the default code by embedding our code. And the file looks like this: 

<div style="text-align:center">
 <h1>
   Welcome to {{ title }}!
 </h1>
</div>
<app-employee-view></app-employee-view>
<app-employee-add></app-employee-add>

10) Run the project: 
Our project is completed, now it’s time to run it. We will run it with the help of : 
 => ng serve –open
At last, our project will be looks like this:

You can also check it on github:

https://github.com/alkavats1/Introduction_to_NGRX.git

Conclusion:

In this blog, we have learned to make a simple project with the help of the state management, NGRX in the Angular. It helps us to manages the state of the application. We learn how the components interact with each other, how to apply and create the actions, reducers, selectors in the app. The concept of “Effect” is good, but the disadvantage of the NGRX is that it adds complexity that affects the code and the code of NGRX is boilerplate.

References:

NgRx Docs

knoldus-advt-sticker