[Angular | nx.dev] Adding NGRX - State Management
Recently I uploaded a post about creating a single project workspace structure using nx.dev and angular. Now it's time to add ngrx to our newly created project. I will continue with the project structure from the previous post.
Setup
Installing ngrx
Prepare Your Workspace
First, we have to add the root level store. This will grow with each feature, by adding feature level states.
In my case I will add the root level store to the node-note application and a feature level state to the data-access-notes library. After that, we will use the store in the feature-note-list to add and display notes.
Root Level Store
Start by creating the root level store with the following command. Make sure to add the correct path to your root module.
nx g ngrx app --module=apps/node-note/src/app/app.module.ts --root
You will see some changes in the import section of your app module. That is the basic initialization for ngrx store and effects. It should be good as it is for now.
Feature Level Store
Now add the feature level store to the data-access-notes library. It's common practice to place your state-relevant code in a folder called '+state'. With the plus as a prefix, it should be always on top of your file tree.
nx g ngrx notes --module=libs/nn-notes/data-access-notes/src/lib/data-access-notes.module.ts --directory +state/notes
-- Is this the root state of the application? (y/N) · false
-- Would you like to use a Facade with your NgRx state? (y/N) · true
This command will create all necessary files and add some basic functionality. In addition to that, it updates the library module with the initialization code we already know from the root level store. But instead of forRoot it calls forFeature.
The store preparations should be done. Let's see how the store works!
Using The Store
For this tutorial, our goal is to be able to create and read notes. In addition to this, we should get an error state if a note with the same id is already in the notes array.
We will use the note-overview component we created in the previous tutorial.
Add a note
Add some basic HTML to be able to create a new note.
Now we have to add some logic to our state that we can add notes. In the feature store command, we checked the facade option. So we have to use the generated facade file to add the note because it should be the only file that gets referenced.
Actions:
Create a new action definition for adding notes. The string parameter defines the internal name, the second parameter defines input parameters.
Reducers:
Reducers are responsible for updating the state. Add the following code to add the new note to the state.
Facade:
Finally, dispatch the action with a new function in the facade.
Now call the facade function inside your recently added add function.
Display a Note
To display the added note we will use the auto-generated allNotes observable inside the facade. But first, we should take a look at what is happening in the selector.
Selector:
The code is quite simple:
export const getNotesState = createFeatureSelector<State>(NOTES_FEATURE_KEY);
const { selectAll, selectEntities } = notesAdapter.getSelectors();
export const getAllNotes = createSelector(getNotesState, (state: State) =>
selectAll(state)
);
The predefined function selectAll does the job for us, returning the entire array of notes.
Switching back to our note list, let's add the following HTML to display the notes.
Now we only have to add the local variable notesList$ and assign allNotes$.
Great, the added notes should now appear!
Error Handling
You may recognize that nothing happens when you add the same Id multiple times.
Effects:
Effects should call your service logic. When we add a note, this is the place to call the backend and, for example, add it to the database. We don't use a backend for this tutorial but we will use an effect to add error handling.
First, add two more actions:
Add a new effect:
Basically, we use an effect for the validation and call different actions for each outcome.
Now we have to make some modifications to the reducer. Change the action on your recently created reducer and add the error reducer:
The selector for the error should already exist:
Now we can finally display the error in our HTML:
Don't forget to define the observable variable in the typescript file:
Source Code:
Georg Hoeller Newsletter
Join the newsletter to receive the latest updates in your inbox.