What Effects? Easily add Data Services to NGRX with EZ-NGRX

EDIT: This article has been picking up readers lately, and I updated the library from “Dynamic NGRX” to “EZNGRX”, and have a new repo. So I’ve updated the article to reflect those changes. Feel free to message me with any questions — I truly believe this is the easiest implementation of NGRX you could possibly imagine.

I had almost 10 readers on my first day with my other post, so as a follow up to my wildly successful first post, I’ve decided to go ahead and add the feature I know you’re all dying for — how do I connect NGRX to async services now since you’ve simplified the process so much?

Well, once again, thankfully, EZNGRX makes it really easy for us to make that happen, and the best part is — you won’t have to write a single effect to make it happen. This tutorial picks up where the previous one left off, using the same source code.

Create and configure the application

In your command prompt, run

ng new ezngrx-todo && cd ezngrx-todo

When the prompts pop up, select “Yes” to Angular routing, and choose your preferred styling format.

When the installation has finished, you should be in the application root directory. We need to now add all the requisite NGRX packages that EZNGRX requires to operate to the project, so run the following:

npm i @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store @ngrx/store-devtools ngrx-store-logger ngrx-store-localstorage @angular/flex-layout @angular/cdk @angular/material --save

Once they finish, now add EZNGRX to the project using the following command:

npm i @woahn/ezngrx --save

You should now be able to run the project using

ng serve

Navigate to http://localhost:4200/, and you should see something like this (except with the name of your app where it says “is running”):

Setup the REST Server

Next, we need to create a backend service that can emulate a REST API. Feel free to handle this however you want, but in my opinion, the easiest way will be to use the json-server library. We can get all the functionality we’ll need in about 30 seconds. First, install the package.

npm install -g json-server

Once you install it, create a file called db.json in the root of the project folder and populate it with the following content.

{
"todo": []
}

Then start the JSON server

json-server --watch db.json

That should be all it takes to get up and going, and you can validate it by going to

http://localhost:3000/todos

You won’t see much, just {} in the top corner of your browser, and it won’t throw an error.

Build the Data Service

Open up app.module.ts to add the Todo interface so it looks like this:

Next, we’ll use the Angular CLI to create the service. Run the following in the terminal

ng g s todo-data

Open up the new file that was just generated, todo-data.service.ts, and modify it to look like the following:

The first thing we do here is extend the DefaultDataService and pass in the Todo interface. The DefaultDataService is what EZNGRX uses by default in all standard actions for all entities. By creating this custom data service, we’re going to replace that service, but we may not actually need to use all of the standard methods in the DefaultDataService. So we extend it instead, and it allows us to write custom methods only for the action we’re going to actually use. The rest will default to the DefaultDataService actions.

We also need to define which entity this data service applies to, so we add the entity property, and assign it the same value as our entity, Todo.

In the last tutorial, we used two simple actions, addOne and removeOne. We’re only going to create data service methods to handle those two functions. The data service methods mirror the actions but just add entity or entities to the end.

load is an initialization function we’ll call that will read all the Todos from the server the first time we load up our application to ensure our local store mirrors what’s on the server.

addOneEntity is pretty straightforward. We use the Angular HttpClient, which returns an Observable. We pass in the Todo interface to define what type of object we can expect to get in return.

The removeOneEntity method is a little bit different. The only thing it passes in is the key of the entity you want to remove. The HttpClient returns something different though, and Dynamic NGRX expects that you’ll send it the key of the entity to remove. So when we get the response back form the HttpClient, we map it to return the initial key that was passed in.

This is all we have to do to get our data service working. While we’re just using the json-server, you can see how easy it would be to connect up to any API. Additionally, if you need to add in other logic or data mapping, this data service is the entry point for inserting that logic.

Update the Dynamic NGRX Config

Last time, we put the config for EZNGRX in the app.module.ts file, but we’re going to be build it up, so let’s break it out into a separate file. Create a new file called ezngrx.config.ts and update it to look like this

We’re defining the data service as a multi-provider that will be imported by the EZNGRX module. We give it the DYNAMIC_DATA_PROVIDER injection token so EZNGRX can find all the relevant data providers, and assign the correct one when it’s needed.

We’ve also enabled logging with the enableLogging parameter. Now when we look in the developer console in the browser, we’ll be able to see the payload for all the NGRX actions that are dispatched and ensure the local state is modifying correctly.

Also, quickly check your app.module.ts file and make sure you have all the right imports configured.

Create the component

Update your app.component.ts file to look like this:

And finally, the last thing we need to do is make a quick modification to app.component.ts to handle the requisite actions. Check out the first article I wrote on this topic for details on what’s going on here.

The load action will call the load method we wrote in todo-data.service.ts. The action accepts two parameters. The first is a query, where you can define the data you want the load method to load. So maybe you only want todo’s created by a specific person, you only want it to load the last 10 created, or some other search parameters. In this instance, we’re just passing in undefined since there isn’t a specific query we want to execute.

The second parameter it accepts is a boolean value on whether to force loading data. By default, the load function checks to see if the entities have already been loaded from the server. If they have been loaded, it doesn’t request the data again. However, if you set the second parameter to true, it will force the load function to download the request from the server, and then replace all the data in the NGRX Store.

All NGRX actions are logged
Look on the network tab, and you’ll see the requests going to the json-server
The db.json file you created will reflect what you have in the application, which represents what we’d expect to see on the server.

That’s it, we’ve now added data services to our ngrx instance, and didn’t have to write a single effects service.

Let me know what you’d like to see next in the comments.

Chief of Staff @ The Future of Work Studios. Husband. Father. TFA. McKinsey & Co. 3X startups. Entrepreneurship, leadership and self-actualization enthusiast.