MyPage is a personalized page based on your interests.The page is customized to help you to find content that matters you the most.


I'm not curious

Ngrx and Angular 2 Tutorial: Building a Reactive Application

Published on 07 July 17
915
0
0

We talk a lot about reactive programming in the Angular realm. Reactive programming and Angular 2 seem to go hand in hand. However, for anyone not familiar with both technologies, it can be quite a daunting task to figure out what it is all about.

In this article, through building a reactive Angular 2 application using Ngrx, you will learn what the pattern is, where the pattern can prove to be useful, and how the pattern can be used to build better Angular 2 applications.

Ngrx and Angular 2 Tutorial: Building a Reactive Application - Image 1

Ngrx is a group of Angular libraries for reactive extensions. Ngrx/Store implements the Redux pattern using the well-known RxJS observables of Angular 2. It provides several advantages by simplifying your application state to plain objects, enforcing unidirectional data flow, and more. The Ngrx/Effects library allows the application to communicate with the outside world by triggering side effects.

What Is Reactive Programming?

Reactive programming is a term that you hear a lot these days, but what does it really mean?

Reactive programming is a way applications handle events and data flow in your applications. In reactive programming, you design your components and other pieces of your software in order to react to those changes instead of asking for changes. This can be a great shift.

A great tool for reactive programming, as you might know, is RxJS.

By providing observables and a lot of operators to transform incoming data, this library will help you handle events in your application. In fact, with observables, you can see event as a stream of events and not a one-time event. This allows you to combine them, for example, to create a new event to which you will listen.

Reactive programming is a shift in the way you communicate between different parts of an application. Instead of pushing data directly to the component or service that needed it, in reactive programming, it is the component or service that reacts to data changes.

A Word about Ngrx

In order to understand the application you will build through this tutorial, you must make a quick dive into the core Redux concepts.

Store

The store can be seen as your client side database but, more importantly, it reflects the state of your application. You can see it as the single source of truth.

It is the only thing you alter when you follow the Redux pattern and you modify by dispatching actions to it.

Reducer

Reducers are the functions that know what to do with a given action and the previous state of your app.

The reducers will take the previous state from your store and apply a pure function to it. Pure means that the function always returns the same value for the same input and that it has no side effects. From the result of that pure function, you will have a new state that will be put in your store.

Actions

Actions are the payload that contains needed information to alter your store. Basically, an action has a type and a payload that your reducer function will take to alter the state.

Dispatcher

Dispatchers are simply an entry point for you to dispatch your action. In Ngrx, there is a dispatch method directly on the store.

Middleware

Middleware are some functions that will intercept each action that is being dispatched in order to create side effects, even though you will not use them in this article. They are implemented in the Ngrx/Effect library, and there is a big chance that you will need them while building real-world applications.

Why Use Ngrx?

Complexity

The store and unidirectional data flow greatly reduce coupling between parts of your application. This reduced coupling reduces the complexity of your application, since each part only cares about specific states.

Tooling

The entire state of your application is stored in one place, so it is easy to have a global view of your application state and helps during development. Also, with Redux comes a lot of nice dev tools that take advantage of the store and can help to reproduce a certain state of the application or make time travel, for example.

Architectural simplicity

Many of the benefits of Ngrx are achievable with other solutions; after all, Redux is an architectural pattern. But when you have to build an application that is a great fit for the Redux pattern, such as collaborative editing tools, you can easily add features by following the pattern.

Although you don’t have to think about what you are doing, adding some things like analytics through all your applications becomes trivial since you can track all the actions that are dispatched.

Small learning curve

Since this pattern is so widely adopted and simple, it is really easy for new people in your team to catch up quickly on what you did.

Ngrx shines the most when you have a lot of external actors that can modify your application, such as a monitoring dashboard. In those cases, it is hard to manage all the incoming data that are pushed to your application, and state management becomes hard. That is why you want to simplify it with an immutable state, and this is one thing that the Ngrx store provides us with.

Building an Application with Ngrx

The power of Ngrx shines the most when you have outside data that is being pushed to our application in real time. With that in mind, let’s build a simple freelancer grid that shows online freelancers and allows you to filter through them.

Setting Up the Project

Angular CLI is an awesome tool that greatly simplifies the setup process. You may want to not use it but keep in mind that the rest of this article will use it.

npm install -g @angular/cli 

Next, you want to create a new application and install all Ngrx libraries:

ng new toptal-freelancers npm install ngrx --save 

Freelancers Reducer

Reducers are a core piece of the Redux architecture, so why not start with them first while building the application?

First, create a freelancers reducer that will be responsible for creating our new state each time an action is dispatched to the store.

freelancer-grid/freelancers.reducer.ts

import { Action } from '@ngrx/store'; export interface AppState { freelancers : Array<IFreelancer> } export interface IFreelancer { name: string, email: string, thumbnail: string } export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); default: return state; } } 

So here is our freelancers reducer.

This function will be called each time an action is dispatched through the store. If the action is FREELANCERS_LOADED, it will create a new array from the action payload. If it is not, it will return the old state reference and nothing will be appended.

It is important to note here that, if the old state reference is returned, the state will be considered unchanged. This means that if you call a state.push(something), the state will not be considered to have changed. Keep that in mind while doing your reducer functions.

States are immutable. A new state must be returned each time it changes.

Freelancer Grid Component

Create a grid component to show our online freelancers. At first, it will only reflect what is in the store.

ng generate component freelancer-grid 

Put the following in freelancer-grid.component.ts

import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-reducer'; import * as Rx from 'RxJS'; @Component({ selector: 'app-freelancer-grid', templateUrl: './freelancer-grid.component.html', styleUrls: ['./freelancer-grid.component.scss'], }) export class FreelancerGridComponent implements OnInit { public freelancers: Rx.Observable<Array<IFreelancer>>; constructor(private store: Store<AppState>) { this.freelancers = store.select('freelancers'); } } 

And the following in freelancer-grid.component.html:

<span class="count">Number of freelancers online: {{(freelancers | async).length}}</span> <div class="freelancer fade thumbail" *ngFor="let freelancer of freelancers | async"> <button type="button" class="close" aria-label="Close" (click)="delete(freelancer)"><span aria-hidden="true">&times;</span></button><br> <img class="img-circle center-block" src="{{freelancer.thumbnail}}" /><br> <div class="info"><span><strong>Name: </strong>{{freelancer.name}}</span> <span><strong>Email: </strong>{{freelancer.email}}</span></div> <a class="btn btn-default">Hire {{freelancer.name}}</a> </div> 

So what did you just do?

First, you have created a new component called freelancer-grid.

The component contains a property named freelancers that is a part of the application state contained in the Ngrx store. By using the select operator, you choose to only be notified by the freelancers property of the overall application state. So now each time the freelancers property of the application state changes, your observable will be notified.

One thing that is beautiful with this solution is that your component has only one dependency, and it is the store that makes your component much less complex and easily reusable.

On the template part, you did nothing too complex. Notice the use of async pipe in the *ngFor. The freelancers observable is not directly iterable, but thanks to Angular, we have the tools to unwrap it and bind the dom to its value by using the async pipe. This makes working with the observable so much easier.

Adding the Remove Freelancers Functionality

Now that you have a functional base, let’s add some actions to the application.

You want to be able to remove a freelancer from the state. According to how Redux works, you need to first define that action in each state that are affected by it.

In this case, it is only the freelancers reducer:

export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', DELETE_FREELANCER: 'DELETE_FREELANCER', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); case ACTIONS.DELETE_FREELANCER: // Remove the element from the array state.splice(state.indexOf(action.payload), 1); // We need to create another reference return Array.prototype.concat(state); default: return state; } } 

It is really important here to create a new array from the old one in order to have a new immutable state.

Now, you can add a delete freelancers function to your component that will dispatch this action to the store:

delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) } 

Doesn’t that look simple?

You can now remove a specific freelancer from the state, and that change will propagate through your application.

Now what if you add another component to the application to see how they can interact between each other through the store?

Read the full article in Toptal blog
We talk a lot about reactive programming in the Angular realm. Reactive programming and Angular 2 seem to go hand in hand. However, for anyone not familiar with both technologies, it can be quite a daunting task to figure out what it is all about.

In this article, through building a reactive Angular 2 application using Ngrx, you will learn what the pattern is, where the pattern can prove to be useful, and how the pattern can be used to build better Angular 2 applications.

Ngrx and Angular 2 Tutorial: Building a Reactive Application - Image 1

Ngrx is a group of Angular libraries for reactive extensions. Ngrx/Store implements the Redux pattern using the well-known RxJS observables of Angular 2. It provides several advantages by simplifying your application state to plain objects, enforcing unidirectional data flow, and more. The Ngrx/Effects library allows the application to communicate with the outside world by triggering side effects.

What Is Reactive Programming?

Reactive programming is a term that you hear a lot these days, but what does it really mean?

Reactive programming is a way applications handle events and data flow in your applications. In reactive programming, you design your components and other pieces of your software in order to react to those changes instead of asking for changes. This can be a great shift.

A great tool for reactive programming, as you might know, is RxJS.

By providing observables and a lot of operators to transform incoming data, this library will help you handle events in your application. In fact, with observables, you can see event as a stream of events and not a one-time event. This allows you to combine them, for example, to create a new event to which you will listen.

Reactive programming is a shift in the way you communicate between different parts of an application. Instead of pushing data directly to the component or service that needed it, in reactive programming, it is the component or service that reacts to data changes.

A Word about Ngrx

In order to understand the application you will build through this tutorial, you must make a quick dive into the core Redux concepts.

Store

The store can be seen as your client side database but, more importantly, it reflects the state of your application. You can see it as the single source of truth.

It is the only thing you alter when you follow the Redux pattern and you modify by dispatching actions to it.

Reducer

Reducers are the functions that know what to do with a given action and the previous state of your app.

The reducers will take the previous state from your store and apply a pure function to it. Pure means that the function always returns the same value for the same input and that it has no side effects. From the result of that pure function, you will have a new state that will be put in your store.

Actions

Actions are the payload that contains needed information to alter your store. Basically, an action has a type and a payload that your reducer function will take to alter the state.

Dispatcher

Dispatchers are simply an entry point for you to dispatch your action. In Ngrx, there is a dispatch method directly on the store.

Middleware

Middleware are some functions that will intercept each action that is being dispatched in order to create side effects, even though you will not use them in this article. They are implemented in the Ngrx/Effect library, and there is a big chance that you will need them while building real-world applications.

Why Use Ngrx?

Complexity

The store and unidirectional data flow greatly reduce coupling between parts of your application. This reduced coupling reduces the complexity of your application, since each part only cares about specific states.

Tooling

The entire state of your application is stored in one place, so it is easy to have a global view of your application state and helps during development. Also, with Redux comes a lot of nice dev tools that take advantage of the store and can help to reproduce a certain state of the application or make time travel, for example.

Architectural simplicity

Many of the benefits of Ngrx are achievable with other solutions; after all, Redux is an architectural pattern. But when you have to build an application that is a great fit for the Redux pattern, such as collaborative editing tools, you can easily add features by following the pattern.

Although you don’t have to think about what you are doing, adding some things like analytics through all your applications becomes trivial since you can track all the actions that are dispatched.

Small learning curve

Since this pattern is so widely adopted and simple, it is really easy for new people in your team to catch up quickly on what you did.

Ngrx shines the most when you have a lot of external actors that can modify your application, such as a monitoring dashboard. In those cases, it is hard to manage all the incoming data that are pushed to your application, and state management becomes hard. That is why you want to simplify it with an immutable state, and this is one thing that the Ngrx store provides us with.

Building an Application with Ngrx

The power of Ngrx shines the most when you have outside data that is being pushed to our application in real time. With that in mind, let’s build a simple freelancer grid that shows online freelancers and allows you to filter through them.

Setting Up the Project

Angular CLI is an awesome tool that greatly simplifies the setup process. You may want to not use it but keep in mind that the rest of this article will use it.

npm install -g @angular/cli Next, you want to create a new application and install all Ngrx libraries:

ng new toptal-freelancers npm install ngrx --save Freelancers Reducer

Reducers are a core piece of the Redux architecture, so why not start with them first while building the application?

First, create a freelancers reducer that will be responsible for creating our new state each time an action is dispatched to the store.

freelancer-grid/freelancers.reducer.ts

import { Action } from '@ngrx/store'; export interface AppState { freelancers : Array } export interface IFreelancer { name: string, email: string, thumbnail: string } export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', } export function freelancersReducer( state: Array = [], action: Action): ArrayIFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); default: return state; } } So here is our freelancers reducer.

This function will be called each time an action is dispatched through the store. If the action is FREELANCERS_LOADED, it will create a new array from the action payload. If it is not, it will return the old state reference and nothing will be appended.

It is important to note here that, if the old state reference is returned, the state will be considered unchanged. This means that if you call a state.push(something), the state will not be considered to have changed. Keep that in mind while doing your reducer functions.

States are immutable. A new state must be returned each time it changes.

Freelancer Grid Component

Create a grid component to show our online freelancers. At first, it will only reflect what is in the store.

ng generate component freelancer-grid Put the following in freelancer-grid.component.ts

import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-reducer'; import * as Rx from 'RxJS'; @Component({ selector: 'app-freelancer-grid', templateUrl: './freelancer-grid.component.html', styleUrls: ['./freelancer-grid.component.scss'], }) export class FreelancerGridComponent implements OnInit { public freelancers: Rx.ObservableArray>; constructor(private store: Store) { this.freelancers = store.select('freelancers'); } } And the following in freelancer-grid.component.html:

span class="count">Number of freelancers online: {{(freelancers | async).length}}span> div class="freelancer fade thumbail" *ngFor="let freelancer of freelancers | async"> button type="button" class="close" aria-label="Close" (click)="delete(freelancer)">span aria-hidden="true">×span>button>br> img class="img-circle center-block" src="{{freelancer.thumbnail}}" />br> div class="info">span>strong>Name: strong>{{freelancer.name}}span> span>strong>Email: strong>{{freelancer.email}}span>div> a class="btn btn-default">Hire {{freelancer.name}}a> div> So what did you just do?

First, you have created a new component called freelancer-grid.

The component contains a property named freelancers that is a part of the application state contained in the Ngrx store. By using the select operator, you choose to only be notified by the freelancers property of the overall application state. So now each time the freelancers property of the application state changes, your observable will be notified.

One thing that is beautiful with this solution is that your component has only one dependency, and it is the store that makes your component much less complex and easily reusable.

On the template part, you did nothing too complex. Notice the use of async pipe in the *ngFor. The freelancers observable is not directly iterable, but thanks to Angular, we have the tools to unwrap it and bind the dom to its value by using the async pipe. This makes working with the observable so much easier.

Adding the Remove Freelancers Functionality

Now that you have a functional base, let’s add some actions to the application.

You want to be able to remove a freelancer from the state. According to how Redux works, you need to first define that action in each state that are affected by it.

In this case, it is only the freelancers reducer:

export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', DELETE_FREELANCER: 'DELETE_FREELANCER', } export function freelancersReducer( state: Array = [], action: Action): ArrayIFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); case ACTIONS.DELETE_FREELANCER: // Remove the element from the array state.splice(state.indexOf(action.payload), 1); // We need to create another reference return Array.prototype.concat(state); default: return state; } } It is really important here to create a new array from the old one in order to have a new immutable state.

Now, you can add a delete freelancers function to your component that will dispatch this action to the store:

delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) } Doesn’t that look simple?

You can now remove a specific freelancer from the state, and that change will propagate through your application.

Now what if you add another component to the application to see how they can interact between each other through the store?

Read the full article in Toptal blog



This blog is listed under Open Source and Development & Implementations Community

Related Posts:
Post a Comment

Please notify me the replies via email.

Important:
  • We hope the conversations that take place on MyTechLogy.com will be constructive and thought-provoking.
  • To ensure the quality of the discussion, our moderators may review/edit the comments for clarity and relevance.
  • Comments that are promotional, mean-spirited, or off-topic may be deleted per the moderators' judgment.
You may also be interested in
 
Awards & Accolades for MyTechLogy
Winner of
REDHERRING
Top 100 Asia
Finalist at SiTF Awards 2014 under the category Best Social & Community Product
Finalist at HR Vendor of the Year 2015 Awards under the category Best Learning Management System
Finalist at HR Vendor of the Year 2015 Awards under the category Best Talent Management Software
Hidden Image Url

Back to Top