1561478203
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
1591447920
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
1624015231
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 it outsourcing services #development outsourcing services #it outsourcing services #managed it outsourcing
1598940617
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.
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!!!
For Installing Angular on your Machine, there are 2 prerequisites:
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.
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:
· After executing the command, Angular CLI will get installed within some time. You can check it using the following command
Now as your Angular CLI is installed, you need to create a workspace to work upon your application. Methods for it are:
To create a workspace:
#angular tutorials #angular cli install #angular environment setup #angular version check #download angular #install angular #install angular cli
1615631710
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
1636488000
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: