Join us on the demo, while our product experts provide a detailed walkthrough of our enterprise platform.

logoAsync

The latest news in the world of engineering.

Identity and Access Management (IAM), including security and customer experience.

Visit Blog
Fuel

Grow your business to millions.Engage and retain your customers.

Visit Blog

Angular State Management With NGXS

NGXS is a state management pattern + library for Angular. It acts as a single source of truth for your application's state, providing simple rules for predictable state mutations.

Akshaya Sharma
Akshaya Sharma
September 08, 2020
6 min read

Free, Secure and Trusted Way to Authenticate Your Visitors

Add login to your website in 5 minutes completely for free!

Free Sign UpNo hidden costs. No credit card needed.

In this article, we will learn about state management in Angular with NGXS. Here we will understand the basic concept of NGXS and create a simple TO-DO App.

What is State

In the bigger apps, managing the data states is very complicated. In angular, each component has its own state, to share the data/state between the components we normally use @Input and @Output decorators, but when the application goes bigger, its challenging to maintain the data consistency. So to solve this problem, redux was introduced. It provides a central store that holds all states of your application. Each component can access the stored state without sending it from one component to another.

Image

What is NGXS

NGXS is a state management pattern + library. It provides as a single source of truth for your application's state, providing simple rules for predictable state mutations.

NGXS is modeled after the CQRS pattern popularly implemented in libraries like Redux and NgRx but reduces boilerplate by using modern TypeScript features such as classes and decorators.

How NGXS works:

NGXS is very simple to use as compared to other state management patterns like redux and Akita. NGXS takes full advantage of angular and typescript over the redux pattern. There are majors 4 concepts to NGXS

1. Store:

It is a global state container and manages the states of the application.We can dispatch the actions to perform certain operations.

    this.store.dispatch(new TodoActions.AddTodo(form));

2. Actions

An action is a type of command which should be called when something happens or you want to trigger at any event like adding a new todo, listing todos etc.

export class AddTodo {
    static readonly type = '[Todo] Add';
    constructor(public payload: ITodo) { }
}

3. State

States are classes along with decorators to describe metadata and action mappings.

import { Injectable } from '@angular/core';
import { State } from '@ngxs/store';

@State<ITodoStateModel[]>({
    name: 'todoList',
    defaults: {
        todoList: [],
    },
})
@Injectable()
export class TodoState {}

4. Select

Selects are functions that slice a specific portion of the state from the global state container i.e. to get the data from the specific global state whenever you want to use.

  @Select(TodoState) todoList$: Observable<ITodo>;

Let's build a To-Do App:

1. Get started

Install the npm install @ngxs/store --save then import the below code in app.module.ts

//File name app.module.ts
import { NgxsModule } from '@ngxs/store';
@NgModule({
  imports: [
    NgxsModule.forRoot([ToDoState], { // here login state 
      developmentMode: !environment.production
    })
  ]
})
export class AppModule {}

2. Create your store

Here we have created a component that dispatches actions to create a to-do and for other operations. Apart from that, we are using a selector TodoState, from which we are listening for the updated to-do list.

Put this code in the app.component.ts

// File name app.component.ts
import { Component } from '@angular/core';
import { Store, Select } from '@ngxs/store';
import { TodoActions } from './state/todo-actions';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { TodoState, ITodo } from './state/todo-state';
import { Observable } from 'rxjs';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'ngxs-todo-app';

  @Select(TodoState) todoList$: Observable<ITodo>;

  addForm = new FormGroup({
    title: new FormControl('', [Validators.required])
  });
  constructor(private store: Store){}
  onSubmit(form: any){
    this.store.dispatch(new TodoActions.AddTodo(form));
  }
  markDone(id: string, is_done: boolean){
    this.store.dispatch(new TodoActions.markDone(id, is_done));
  }
}

3. Create your actions

Create a folder state and put the todo-actions.ts file and add below code

// File name todo-actions.ts
export class AddTodo {
    static readonly type = '[Todo] Add';
    constructor(public payload: any) { }
}

export class EditTodo {
    static readonly type = '[Todo] Edit';
    constructor(public payload: any) { }
}

export class FetchAllTodos {
    static readonly type = '[Todo] Fetch All';
}

export class DeleteTodo {
    static readonly type = '[Todo] Delete';
    constructor(public id: number) { }
}

4. Create your State:

Here we have created the state of the todo, it contains the global state of the todo list. Create a folder state and put the todo-state.ts file and add below code

// File name todo-state.ts
import { Injectable } from '@angular/core';
import { State, NgxsOnInit, Action, StateContext } from '@ngxs/store';
import { TodoActions } from './todo-actions';
import { patch, updateItem } from '@ngxs/store/operators';

export interface ITodo {
    id: string;
    title: string;
    is_done: boolean;
}
export interface ITodoStateModel {
    todoList: ITodo[];
}
@State<ITodoStateModel>({
    name: 'todoList',
    defaults: {
        todoList: [],
    },
})
@Injectable()
export class TodoState implements NgxsOnInit {
    ngxsOnInit(ctx) {
        ctx.dispatch(new TodoActions.FetchAllTodos());
    }
    @Action(TodoActions.markDone)
    markDone(
      ctx: StateContext<ITodoStateModel>, 
      { payload, is_done }: TodoActions.markDone
    ) {
        ctx.setState(
            patch({
                todoList: updateItem(
                  (item: ITodo) => item.id === payload, 
                  patch({ is_done: !is_done })
                )
            })
        );
    }

    @Action(TodoActions.AddTodo)
    add(
        ctx: StateContext<ITodoStateModel>,
        { payload }: TodoActions.AddTodo,
    ) {
        const state = ctx.getState();
        ctx.setState({
            ...state,
            todoList: [
                ...state.todoList,
                {
                    ...payload,
                    id: Math.random().toString(36).substring(7),
                    is_done: false
                }
            ],
        }
        );
    }

}

5. Create your html view

Here we have created a form that we use to create todo and listed all todos. put this code in your app.component.html

<!-- File name  app.component.html -->
<form [formGroup]="addForm" (ngSubmit)="onSubmit(addForm.value)">
  <input type="text" formControlName="title" class="form-control todo-list-input" placeholder="What do you need to do today?">
  <button class="add btn btn-primary font-weight-bold todo-list-add-btn">Add</button> 
</form>
<ul class="d-flex flex-column-reverse todo-list">
    <li *ngFor="let todo of (todoList$ | async) ?. todoList" [ngClass]="{'completed': todo.is_done}">
      <div class="form-check"> 
        <label class="form-check-label"> 
          <input (click)="markDone(todo.id, todo.is_done)" class="checkbox" type="checkbox" [checked]="todo.is_done">{{todo.title}} <i class="input-helper"></i></label> 
      </div>
    </li>
  </ul>

After lots of code, it's time to see the results. So here is the UI you will get. To get the complete code please go to Github Repo. Image

Conclusion

We have gone through the basic concepts of NGXS and built a simple to-do app. There are a lot of advanced features and plugins by NGXS, but beyond the scope, we could not add, but hopefully, we will be exploring in future blogs.



LoginRadius Docs

Implement Authentication in Minutes

click here

Most Popular Tags

EngineeringJavaScriptReactAuthenticationNodeJsCSSSecurityC#JWTOAuth

Do you want a free authentication solution?

Add the world's most secure, reliable and easy to implement user authentication solution on your applications at $0Get Started Free

Akshaya Sharma

Akshaya Sharma

Akshaya Sharma is a Software Engineer at LoginRadius and loves to work on javascript and frameworks.

View Profile

Try a Modern Authentication Solution

$0/ month

Free Sign Up
  • 7,000 Monthly Active Users
  • 1 Web or Mobile App
  • Email/Password Login
  • 3 Social Login Providers
  • User Data Storage
  • Transactional Email Template
  • Customizable Login Interfaces