Michio JP

Michio JP

1561478203

Simple state management in Angular with only Services and RxJS

Simple state management in Angular with only Services and RxJS - In this write up, I’ll show you a simple way of managing state by only using RxJS and Dependency Injection, all of our component tree will use …

One of the most challenging things in software development is state management. Currently there are several state management libraries for Angular apps: NGRX, NGXS, Akita… All of them have different styles of managing state, the most popular being NGRX, which pretty much follows the FLUX/Redux principles from React world (basically using one way data flow and immutable data structures).

But what if you don’t want to learn, setup, and use an entire state management library for a simple project, what if you want to manage state by only using tools you already know well as an Angular developer, and still get the performance optimisations and coherency that state management libraries provide (On Push Change Detection, one way immutable data flow).

DISCLAIMER: This is not a post against state management libraries. We do use NGRX at work, and it really helps us to manage very complex states in very big and complex applications, but as I always say, NGRX complicates things for simple applications, and simplifies things for complex applications, keep that in mind.

In this write up, I’ll show you a simple way of managing state by only using RxJS and Dependency Injection, all of our component tree will use OnPush change detection strategy.

Imagine we have simple Todo app, and we want to manage its state, we already have our components setup and now we need a service to manage the state, let’s create a simple Angular Service:

// todos-store.service.ts

@Injectable({provideIn: 'root'})
export class TodosStoreService {

}


So what we need is, a way to provide a list of todos, a way to add todos, remove, filter, and complete them, we’ll use getters/setters and RxJS’s Behaviour Subject to do so:

First we create ways to read and write in todos:

// todos-store.service.ts

@Injectable({provideIn: 'root'})
export class TodosStoreService {

  // - We set the initial state in BehaviorSubject's constructor
  // - Nobody outside the Store should have access to the BehaviorSubject 
  //   because it has the write rights
  // - Writing to state should be handled by specialized Store methods (ex: addTodo, removeTodo, etc)
  // - Create one BehaviorSubject per store entity, for example if you have TodoGroups
  //   create a new BehaviorSubject for it, as well as the observable$, and getters/setters
  private readonly _todos = new BehaviorSubject<Todo[]>([]);

  // Expose the observable$ part of the _todos subject (read only stream)
  readonly todos$ = this._todos.asObservable().pipe(
    /** shareReplay does two things, caches the last emitted value, 
        so components that subscribe after a value been emitted can still display the value,
        and shares the same observable between all observers, 
        instead of creating new observables on each subscription
    */
    shareReplay(1) 
  )

  // the getter will return the last value emitted in _todos subject
  get todos(): Todo[] {
    return this._todos.getValue();
  }

  // assigning a value to this.todos will push it onto the observable 
  // and down to all of its subsribers (ex: this.todos = [])
  set todos(val: Todo[]) {
    this._todos.next(val);
  }

  addTodo(title: string) {
    // we assaign a new copy of todos by adding a new todo to it 
    // with automatically assigned ID ( don't do this at home, use uuid() )
    this.todos = [
      ...this.todos, 
      {id: this.todos.length + 1, title, isCompleted: false}
    ];
  }

  removeTodo(id: number) {
    this.todos = this.todos.filter(todo => todo.id !== id);
  }

}


Now let’s create a method that will allow us to set todo’s completion status:

// todos-store.service.ts

setCompleted(id: number, isCompleted: boolean) {
  let todo = this.todos.find(todo => todo.id === id);

  if(todo) {
    // we need to make a new copy of todos array, and the todo as well
    // remember, our state must always remain immutable
    // otherwise, on push change detection won't work, and won't update its view    

    const index = this.todos.indexOf(todo);
    this.todos[index] = {
      ...todo,
      isCompleted
    }
    this.todos = [...this.todos];
  }
}


And finally an observable source that will provide us with only completed todos:

// todos-store.service.ts

// we'll compose the todos$ observable with map operator to create a stream of only completed todos
readonly completedTodos$ = this.todos$.pipe(
  map(todos => this.todos.filter(todo => todo.isCompleted))
)


Now, our todos store looks something like this:

// todos-store.service.ts

@Injectable({providedIn: 'root'})
export class TodosStoreService {

  // - We set the initial state in BehaviorSubject's constructor
  // - Nobody outside the Store should have access to the BehaviorSubject 
  //   because it has the write rights
  // - Writing to state should be handled by specialized Store methods (ex: addTodo, removeTodo, etc)
  // - Create one BehaviorSubject per store entity, for example if you have TodoGroups
  //   create a new BehaviorSubject for it, as well as the observable$, and getters/setters
  private readonly _todos = new BehaviorSubject<Todo[]>([]);

  // Expose the observable$ part of the _todos subject (read only stream)
  readonly todos$ = this._todos.asObservable().pipe(
    /** shareReplay does two things, caches the last emmited value, 
        so components that subscribe after a value been emmited can still display the value,
        and shares the same observable between all observers, 
        instead of creating new observables on each subscription
    */
    shareReplay(1) 
  )

  // we'll compose the todos$ observable with map operator to create a stream of only completed todos
  readonly completedTodos$ = this.todos$.pipe(
    map(todos => this.todos.filter(todo => todo.isCompleted))
  )

  // the getter will return the last value emitted in _todos subject
  get todos(): Todo[] {
    return this._todos.getValue();
  }

  // assigning a value to this.todos will push it onto the observable 
  // and down to all of its subsribers (ex: this.todos = [])
  set todos(val: Todo[]) {
    this._todos.next(val);
  }

  addTodo(title: string) {
    // we assaign a new copy of todos by adding a new todo to it 
    // with automatically assigned ID ( don't do this at home, use uuid() )
    this.todos = [
      ...this.todos, 
      {id: this.todos.length + 1, title, isCompleted: false}
    ];
  }

  removeTodo(id: number) {
    this.todos = this.todos.filter(todo => todo.id !== id);
  }

  setCompleted(id: number, isCompleted: boolean) {
    let todo = this.todos.find(todo => todo.id === id);

    if(todo) {
      // we need to make a new copy of todos array, and the todo as well
      // remember, our state must always remain immutable
      // otherwise, on push change detection won't work, and won't update its view
      const index = this.todos.indexOf(todo);
      this.todos[index] = {
        ...todo,
        isCompleted
      }
      this.todos = [...this.todos];
    }
  }

}


Now our smart components can access the store and manipulate it easily:

// app.component.ts

export class AppComponent  {
  constructor(public todosStore: TodosStoreService) {}
}

<!-- app.component.html -->

<div class="all-todos">

  <p>All todos</p>

  <app-todo 
    *ngFor="let todo of todosStore.todos$ | async"
    [todo]="todo"
    (complete)="todosStore.setCompleted(todo.id, $event)"
    (remove)="todosStore.removeTodo($event)"
  ></app-todo>
</div>


And here is the complete and final result:

Full example on StackBlitz with a real REST API

This is a scalable way of managing state too, you can easily inject other store services into each other by using Angular’s powerful DI system, combine their observables with pipe operator to create more complex observables, and inject services like HttpClient to pull data from your server for example. No need for all the NGRX boilerplate or installing other State Management libraries. Keep it simple and light when you can.

#angular

What is GEEK

Buddha Community

Simple state management in Angular with only Services and RxJS
Marcelle  Smith

Marcelle Smith

1591447920

Angular State Management in RxJS Services

Most Angular applications need some amount of state management. In some applications, a state management library like NgRX or Akita might make sense. But many times storing application state in RxJS services will work perfectly. We’ll go over how to do this using RxJS BehaviorSubjects and Observables.

#rxjs #angular #state management

Ajay Kapoor

1624015231

Best Managed IT Outsourcing Services in India

PixelCrayons works with its clients as an “outsourced IT department” by managing applications, mobile devices, networks, servers, databases, patching, upgrades, IT security, and end-user support.

Our development outsourcing services will provide 1st, 2nd and 3rd line support to your end-users and take care of your infrastructure, to your fixed hours plus standard SLAs, whilst making sure the results are fully aligned to your business goals.

Signs Strict NDA
Flexible Engagement Models
50% Cheaper & 2X faster
100% Money-Back Guarantee
Contact Us Now

managed outsourcing services

#managed outsourcing services #managed it outsourcing services #development outsourcing services #it outsourcing services #managed it outsourcing

Christa  Stehr

Christa Stehr

1598940617

Install Angular - Angular Environment Setup Process

Angular is a TypeScript based framework that works in synchronization with HTML, CSS, and JavaScript. To work with angular, domain knowledge of these 3 is required.

  1. Installing Node.js and npm
  2. Installing Angular CLI
  3. Creating workspace
  4. Deploying your First App

In this article, you will get to know about the Angular Environment setup process. After reading this article, you will be able to install, setup, create, and launch your own application in Angular. So let’s start!!!

Angular environment setup

Install Angular in Easy Steps

For Installing Angular on your Machine, there are 2 prerequisites:

  • Node.js
  • npm Package Manager
Node.js

First you need to have Node.js installed as Angular require current, active LTS or maintenance LTS version of Node.js

Download and Install Node.js version suitable for your machine’s operating system.

Npm Package Manager

Angular, Angular CLI and Angular applications are dependent on npm packages. By installing Node.js, you have automatically installed the npm Package manager which will be the base for installing angular in your system. To check the presence of npm client and Angular version check of npm client, run this command:

  1. npm -v

Installing Angular CLI

  • Open Terminal/Command Prompt
  • To install Angular CLI, run the below command:
  1. npm install -g @angular/cli

installing angular CLI

· After executing the command, Angular CLI will get installed within some time. You can check it using the following command

  1. ng --version

Workspace Creation

Now as your Angular CLI is installed, you need to create a workspace to work upon your application. Methods for it are:

  • Using CLI
  • Using Visual Studio Code
1. Using CLI

To create a workspace:

  • Navigate to the desired directory where you want to create your workspace using cd command in the Terminal/Command prompt
  • Then in the directory write this command on your terminal and provide the name of the app which you want to create. In my case I have mentioned DataFlair:
  1. Ng new YourAppName

create angular workspace

  • After running this command, it will prompt you to select from various options about the CSS and other functionalities.

angular CSS options

  • To leave everything to default, simply press the Enter or the Return key.

angular setup

#angular tutorials #angular cli install #angular environment setup #angular version check #download angular #install angular #install angular cli

Revenue Cycle Management Software Services and Custom Integration - SISGAIN

Revenues come day in day out and it becomes strenuous to keep a track of them. With the help of Revenue cycle management software, one is able to perform the hospital revenue cycle management in Oklahoma, USA in a much simplified and easy manner. Our skilful developers and engineers created the healthcare revenue cycle management software that is convenient to use by its users and meets the customers requirement. We happen to be one of the notable revenue cycle management companies, facilitating the needs of our customers and being efficient and useful in performance. For more information call us at +18444455767 or email us at hello@sisgain.com

#revenue cycle management #revenue cycle management software #revenue cycle management companies #hospital revenue cycle management #revenue cycle management services #revenue cycle management solutions

Cómo Usar El Operador SwitchMap En RxJS En angular

Tutorial sobre el uso del operador switchMap en #RxJS (ReactiveX) en #Angular. Dura más de lo habitual debido a que lo explicamos con dos ejemplos, uno muy básico y uno de los típicamente llamados "Ejemplo de la Vida Real" (Real life example). Para ver los puntos más importantes, les dejamos los siguientes minutos:

#rxjs #angular