NGRX made easy — a tutorial to add NGRX in any project <5 minutes
In this tutorial, I’m going to demonstrate the fastest way to get full NGRX functionality into your application, utilizing the Dynamic NGRX library.
We’re going to build a very simple “ToDo” app. This article is for developers who are interested in using NGRX, but might be scared away by the sheer volume of boilerplate required to get started, developers who are sick of all the boilerplate and looking to simplify their lives, or developers that just want the easiest way possible to implement NGRX into their project.
If you were to approach the Todo list with a traditional NGRX method, you would have to do something like create
todo.selectors.ts , build a Todo interface, and then configure and add the NGRX store module to your project. And that’s just to get the basic functions working. Then, if you wanted to persist the data, you’d still need to add
todo.service.ts to handle your http requests and
todo.effects.ts plus updating your actions file and reducers to handle all the new functionality. It makes me tired just thinking about it!
It’s a lot to just do something as simple as building a checklist, and frankly, sometimes rather overwhelming when you just want to get started.
That’s where Dynamic NGRX comes in. This library greatly simplifies this process by virtually eliminating all of the boilerplate, and allowing for the full NGRX functionality with a just few lines of configuration.
This tutorial assumes you’ve already set up the Angular CLI on your machine, and are familiar with its basic usage. So, without further ado, let’s get started.
Set up the project
Start by creating a new project.
ng new ez-ngrx
Hit “N” for routing and “SCSS” for styling. Your project will get initialized, and change to that directory
Now we need to install the package dependencies, which includes all of the NGRX libraries. We’ll also install the NGRX localstorage module for data persistence and logger module for development purposes. Yes, there are a lot of dependencies, and man, this would be super daunting if we actually had to work with all of them. Thankfully, Dynamic NGRX will take care of that for us.
npm i @ngrx/effects @ngrx/entity @ngrx/router-store @ngrx/store @ngrx/store-devtools ngrx-store-localstorage ngrx-store-logger --save
npm i @angular/material @angular/cdk @angular/flex-layout --save
Finally, add the Dynamic NGRX library.
npm i dynamic-ngrx --save
Alright, now we’re ready to get started. If you run
in your console, and navigate to “http://localhost:4200" in your browser, you should see the default project page like this:
Layout the Framework
Let’s start by importing the modules to the project. Open up
app.module.ts and import the required modules to the project as follows:
Then, we need to enable the Angular Material theme styling. Create a file called
src/theme.scss and copy the following
By default, Angular Material doesn’t define a theme, so we need to tell it what theme and colors to use in our project. It comes with handful or predefined ones, but we’re just going to create our own.
Now we need to import the Angular Material theme settings into our project. Open the
src/styles.scss file generated by the Angular CLI, and add the following to it
I always throw in the margin around cards, because for some reason the margin is set to 0 by default in Angular Material and it always looks bad if you don’t.
Then, open up the
app.component.html file and add the following
If everything is working correctly, your browser should now look like this
Thus far, all we have done is imported the Angular Material theme library, done some minor formatting with the card, and created the basic layout for the todo list.
Adding Logic to the Component
From here, we’re going to add some logic to the component and make our list to start populating some “Todo’s”.
The first thing we’re going to do is get a way to collect the text from the input field. With Angular, there are at least 3 different ways I can think of we could use to make this happen (i.e. template driven form, reactive form and using an element reference). We’re going to use the element reference, because I also want to just make it add the “Todo” as soon as you hit “Enter” in the input field without having to add a button.
Go back into the
app.component.html file, and add a template variable and keyup listener to the input field.
There are two main things we’ve done here.
First, we added
(keyup) to the input element.
#todoInput assigns a variable to the input field, which we can either access directly in the HTML template, or we can access it from the component controller. The
(keyup) property binds a listener to the input field, and allows us to attach a method to the listener, that will get called after every “keyup” event from the input field.
Second, we added a
button element to the action list that will populate the action list with the “Todos” we add to our list. We’re not going to do anything too fancy yet with the list, we’re just going to iterate through the “Todos” that get added to the list.
I’m going to quickly add an interface for the
Todo entity. For simplicity’s sakes, I’ve just added it to
app.module.ts but you can add it wherever you’d like, as some people like to put it in their own
models file for organization.
Let’s now get the data from the input field in the component controller. Open up
app.component.ts and add the following.
First, we’ve added the
@ViewChild decorator which allows us to access the template variable,
todoInput , which is the input element
#todoInput we declared in the earlier step. We can now access this element within our component controller.
Second, we’ve added an array “todos” that will hold the elements to be iterated in the template.
Third, we added an
addTodo method that receives a KeyboardEvent for input. Every keyboard event has a numeric keyCode associated with it. The only one we care about is when the user hits “Enter”, which has a keyCode of “13”. We’re going to ignore the rest of the keyup events.
When “Enter” is pressed, we’ve imported a quick library to generate a unique ID for the todo ID, and then we grab the text from the input element, and push it to the todo array and then it resets the input field value.
Finally, we’ve added a
removeTodo method that will remove a Todo from our list when we click on it.
With this functionality in the controller, if you go back to the browser, your Todo list should work. You should be able to type into the input field, hit enter, and see it show up in the Todo list. You should also be able to click on any of the todo’s, and they will be removed.
Bring in NGRX
Alright, so this is awesome and all, but now it’s time for us to add the functionality you’ve all come here for — how to add NGRX in the simplest manner you’ve ever seen.
First things first, let’s go back and add Dynamic NGRX to the
There are two things we’ve added here. First is the config object. The two properties we have are
entities property is a collection of entities we want to add to the application. To start with, we just add a single “Todo” entity to the collection.
This is one of the most magical parts of Dynamic NGRX, as this is all you have to do to add another entity class. With conventional NGRX, if you wanted to add a “Todo” entity to your store, first you’d have to define the reducer state, and add the reducers, then create the actions you wanted to add, and then define some entity selectors. Now, with Dynamic NGRX, all you have to do is add an object to the
entities collection and you’re off to the races. We’ll see how to utilize it in your application shortly.
The second property,
providers is honestly just there to resolve an issue that will pop up with Angular’s AOT compiler. At a future date when we add data services to our application, we’re going to need to declare some providers here. However, if it’s empty and we don’t include the property, Angular will throw an error. I’ve spent a ton of time fighting this one, and have yet to be victorious in removing that property. I’m hopeful someone down the road can help me figure out how to make it not necessary. I’ll do a future tutorial where we’ll use that property, but for now, just declare an empty array.
Once we have our store configuration defined, we pass that configuration object to the
DynamicNgrxModule root method to initialize it.
Aaaannddd… that’s it. That is literally all you have to add to get access to the full library of NGRX functionality. Through those few lines of code you added, you now have reducers, entity selectors, actions, effects, observables, etc.
Where’s my Staples “That was easy” button?
Let’s connect it up to our component now. Update your
app.component.ts with the following
So there are a handful of changes here to call out, so follow along with me, one step at a time.
The first change is we’re importing the
DyanmicFacadeService and the NGRX Store. I’ll discuss more about the store later, but the
DynamicFacadeService is basically a factory that generates an instance of a facade tailored around the entity you have defined. If you aren’t familiar with facades, read here for more details. They’re basically a single service that you can use to interface with to access all the NGRX functions. There’s a lot of debate over the benefit of facades, with some definite pros and cons, but personally for the sake of simplicity and speed of development, I’m a huge fan of them and Dynamic NGRX utilizes them exclusively.
this.todoFacade = this.dynamicFacadeService.getFacade<Todo>(‘Todo’);
Once we import the
DynamicFacadeService, we call the
getFacade function, pass in an interface describing the entity, the name of the entity, and it returns a facade that will be the way we’ll interact with NGRX.
this.todos$ = this.todoFacade.entities$;
We then use the Todo facade we created to access the
entities$ property, which will return an observable array of all the Todos in the store. This is just one of the many properties on the Todo facade we can access. Other common properties include
selectedEntity$, etc. which become really useful as we get into more advanced functionality with data providers and selecting specific entities.
You’ll note that we are importing the NGRX
store object. We utilize this in the
addTodo method, where we use the store dispatch method to dispatch new actions, like adding a new Todo.
Now you might be thinking, “Why do we have to import the store and dispatch a new action? Why don’t you just import the store to the facade, and add an ‘addOne’ method that automatically dispatches an
[Add One] action?” Well, as Sam Julien discusses in his excellent article discussing the pros and cons of facades, there comes some traceability issues later down the road for debugging, as it becomes difficult to trace where the
[Add One] action was dispatched.
Instead, we use the facade to generate the action itself. The
addOne method takes an instance of the entity, and will dispatch all the necessary plumbing to add the object to the NGRX store. The
removeTodo method has been updated to follow a similar pattern.
One the action has been dispatched, out
entities$ observable will return the updated value, and then update the view. Speaking of which, let’s update the view to use this new observable.
The main change is we modified the
ngFor iterator to use the new todo entity observable, and added the async pipe.
If all is well, your application shouldn’t look any different, but there’s a whole lot more going on now.
You should now be able to add Todos to your list and remove them as before. However, if you have the Redux Devtools plugin installed, you’ll see there’s a lot more going on in the background in your developer console.
Awesome! You now have a fully functional NGRX todo list, and you created it with what I can only hope was a minimal amount of pain to get up and running.
The only thing left that’s annoying is your Todo list completes itself every time you refresh your browser (the data doesn’t persist and the list resets).
Fortunately, Dynamic NGRX made this really easy for you to handle. All you have to do is go into your
app.module.ts file and modify the config object to enable offline sync. Once you add that property, all of your Todos should automatically persist through page reloads.
I’ve uploaded the project file to Github for your reference.
If you’ve enjoyed this tutorial, please check out the next one — it demonstrates how to connect up a back end service without having to use any effects.
This concludes my first tutorial on making NGRX easy using Dynamic NGRX. If you liked it, please give me a clap or share your thoughts in the comments. Thanks for the read!