Learn how to use Firestore as a backend for NgRx. This episode combines the power @ngrx/entity with AngularFire2 State Changes for fine-grained control over your data. https://angularfirebase.com/lessons/state-changes-angularfire2-with-ngrx/

Angular Air #135: https://youtu.be/t-auGKG1yjs
NgRx: https://github.com/ngrx/platform
Firestore: https://cloud.google.com/firestore/docs/
Inspiration: https://www.booth.fi/
2024-02-04T07:55:01.375Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
87344aff-7b56-44d0-a097-e693ab1ec2fb
4f36a62a4de21661d36daf76b248c2c169557798eae571321a2cafc006b7101f
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
A few weeks ago, I showed you how to use NGRX entity adapters.
Today, I'm going to build on this concept and show you how to use Firestore as a persistent back end data source.
You might be aware that AngularFire version 5 has a new state changes method, which we're going to take advantage of in this episode.
It makes it possible to keep track of when documents are added, modified or removed.
If you want an example of how this might be used, look no further than the Firebase console itself.
If we add a new value to the database, you'll see It flashes green for a split second.
And, the document itself is modified so it flashes orange.
If we remove the property, then it flashes red.
The Firestore web console happens to be built with NGRX, which I learned by watching Angular Air episode 135.
So make sure to check that out as well.
If you're new here, click the subscribe button and follow along with the source code at angularfirebase.com.
To get started, I'm going to first show you how we have this App setup based on the previous video.
Starting with the app module, the main change we made is we installed AngularFire 2 along with Firestore.
I'm also including the ngrx effects module and in the root, just passing it an empty array.
If you're lost at this point, Make sure to go back and watch the n g r x entity video.
From there, I'm going to go into our pizza feature module And I have a new file called pizza effects that we're going to create later.
We also import the effects module here but call for feature and pass it the pizza effects file.
The actual app we're building is just a collection of pizzas, and the user has the ability to asynchronously update them from a status of cooking to delivered.
The thing that's interesting is that this app is going to listen for the state changes coming from AngularFire 2 and then use entity adapters to update the local data store.
Currently, I've queried all the pizzas that have a status of cooking.
So if the status changes from anything other than cooking, it should be removed from our local data store.
If we update the status from cooking to delivered, you'll see that it gets removed from the local data store and that action is triggered here in Redux DevTools.
The key takeaway here is that you'll always know how your data is changing relative to the way you queried it from Firestore.
Let's go ahead and set up the n g r x actions that make this possible.
The first action is query.
Eventually, it's going to make a query to Firestore and listen to any changes that happened to that data.
And from there, we're going to set up added, modified, and removed.
It's important that you keep these names consistent because they're returned to us from AngularFire 2.
I also wanna show you how to update data on a Firestore document.
So we'll set up actions for update and success.
Each of these actions will have a class that implements the action interface and has a custom payload that we define in the constructor.
The query action doesn't need a payload, But the added action will return an individual pizza object, so we can type that to our pizza interface.
Then modified hide and removed will also follow the same exact pattern.
They simply create a payload of a pizza object.
The update action is a little more interesting.
It's going to take an entity ID as well as a partial piece of data that we wanna update on the interface.
Normally, TypeScript wouldn't let us do this, but we can use The partial type with our pizza interface to update individual properties on the object.
The success action is only used to show us when a successful Update operation has been completed, so there's no need to add a payload to it.
Then the final step is to export all these actions as a single type.
Now we're going to jump into the reducer and I'll go through the whole thing from top to bottom.
So first, we're gonna import the actions We just created as well as a few things here from NGRX, then we'll define our pizza interface, which just has an ID, a size and a status which can either be cooking or delivered.
Then we can use this interface to initialize our adapter.
This will give us access to a bunch of helper methods to update the state consistently.
From there, we use entity state to extend the main state interface.
This ensures that our data conforms to a specific format for entity.
And if you have some initial data you wanna set as the initial state, you would do that here, but for now I'm just going to leave it blank.
Now we're ready to build the reducer function.
It takes the old state as well as the action that's being dispatched, which will be one of our pizza actions.
And then we'll set up the switch statement here And the first one we'll look for is added.
So whenever we get a new item that's added, we're going to add 1 pizza to the state.
That will add one new pizza to the state and keep track of its ID and everything automatically.
For modified, we'll call update 1, then pass it the entity ID as well as the changes that we wanna make.
Then the same basic idea for removed, but this time we'll call remove 1.
And it takes the ID as the argument.
With just these three actions in the reducer, we can throw around all kinds of different asynchronous events while providing a ton of feedback about our local data store.
The last step is to create the selectors that allow us to slice various pieces of the state.
That's done by calling create feature selector And then n g r x gives us a bunch of built in helper methods, or you can create your own to slice different pieces of the state.
In this demo, we're only gonna be using select all.
Now we're ready to build the n g r x effect.
The effect will allow us to isolate asynchronous events, So we don't have to actually trigger those events from inside a component.
In other words, components should only dispatch events and select parts of the store.
They shouldn't cause any asynchronous side effects on their own.
We're also gonna be using the new loadable operators from RxJS 5 point 5.
So the import syntax is slightly different as you see here.
The first thing I'm going to do is inject the actions as well as the Angular Firestore library in the constructor.
The most important effect here is query, and that's going to make the query to Firestore for collection and handle the added, modified, removed events that come from that collection.
So first, we call actions of type with the query action.
That returns an observable, so we can pipe multiple RxJS operators here, which will make our code more readable than it has been in previous tutorials that I've shown you about NGRX The next step is to make a query to Firestore.
So we do that by calling AngularFirestore collection, and then we're going to Only query the pizzas that have a status of cooking.
Then to get an n g r x friendly observable from Firestore, we call state changes.
That returns an array of actions, so we'll map that down to each individual action by calling merge map.
Then we can dispatch the correct action based on what's returned from Firestore.
So we'll call pizza with the action type, which will be added, modified, or removed.
And then the payload will be the actual data that we update on the local store.
We want both the data and the document ID so we can map those together here in the object.
That's all there is to it.
Your local data store will now stay in sync with the data in Firebase Airbase and you'll have a lot of flexibility for managing those changes.
But we're not quite done yet.
I still wanna set up one more effect so the user can manually update data in Firestore.
This time we're going to listen to the update action and when that occurs we'll map it down to the data payload.
That has the document ID as well as the data that we want to update.
From that point, we call switch map and then with the data that we wanna Update will make a reference to that pizza in Firestore.
Then the update action is going to return a Promise, so we're going to create an observable from that Promise.
To take care of that, you can do Observable from Promise and then make the update inside of it.
And lastly, we'll map that down Onto the success action once that promise resolves successfully.
It also be a good idea to catch errors here and dispatch an error action, but I'm skipping that part for now.
We're almost done at this point.
We just need a component for the end user to interact with.
We'll go ahead and import ngrxstore as well as the actions and reducer that we just created.
Then our actual observable will be an array of pizzas.
The store is injected in the constructor and it's typed to our pizza interface.
We'll make the initial query during n g on a net, but first, we'll select the slice of the store we want for our pizza's variable.
After that, all we have to do is dispatch the query action.
And our front end is going to have some buttons where the user can update the state of an individual pizza.
The update pizza method is an event handler that will bind to a button click, and we can just dispatch the update action with the corresponding payload.
The HTML code is incredibly simple.
We just loop over the array of pizzas, and then for each one, we'll add that update status button.
Clicking this button will trigger an asynchronous write operation, which will update the pizza from a status of cooking to delivered.
Now let's go into the app and take a closer look at what's actually happening here.
The initial page load pulls the data from Firestore and then adds it to the state in the entity format.
If you look at the actions, we first have a query pizzas action and then we have 4 added events after that.
And of course, that gives us 4 pizzas on the screen here as well.
Now let's see what happens when we click the Update Status button.
We get 3 actions here.
First, the update And then it's removed from the local store, then update success after the actual update promise resolves.
So even though the pizza wasn't removed from Firestore, you still get the removed action because it was removed from the local store.
You could use that state change to toggle a CSS class or show a Toast message or any other UI element you can Now let's take a look at one more thing.
What happens if we update a property on a pizza from Firestore or any other client subscribing to this data?
You'll see down here in DevTools, we get a modified action, which tells us that the data on the pizza was updated, but it still remains in our base query.
The end result is that you now have a system that will detect changes in Firestore and tell you exactly how they affect your local NGRX store.
That's it for NGRX with AngularFire 2.
If this video helped you, please like and subscribe.
And if you wanna learn more every week, consider becoming a pro subscriber at angularfirebase.com.
You'll get access to exclusive content, a free copy of my book, as well as a bunch of other resources designed to help you get your app off the ground.
Thanks for watching, and I'll see you soon.

Speaker 0: A few weeks ago, I showed you how to use NGRX entity adapters. Today, I'm going to build on this concept and show you how to use Firestore as a persistent back end data source. You might be aware that AngularFire version 5 has a new state changes method, which we're going to take advantage of in this episode. It makes it possible to keep track of when documents are added, modified or removed. If you want an example of how this might be used, look no further than the Firebase console itself.

If we add a new value to the database, you'll see It flashes green for a split second. And, the document itself is modified so it flashes orange. If we remove the property, then it flashes red. The Firestore web console happens to be built with NGRX, which I learned by watching Angular Air episode 135. So make sure to check that out as well.

If you're new here, click the subscribe button and follow along with the source code at angularfirebase.com. To get started, I'm going to first show you how we have this App setup based on the previous video. Starting with the app module, the main change we made is we installed AngularFire 2 along with Firestore. I'm also including the ngrx effects module and in the root, just passing it an empty array. If you're lost at this point, Make sure to go back and watch the n g r x entity video.

From there, I'm going to go into our pizza feature module And I have a new file called pizza effects that we're going to create later. We also import the effects module here but call for feature and pass it the pizza effects file. The actual app we're building is just a collection of pizzas, and the user has the ability to asynchronously update them from a status of cooking to delivered. The thing that's interesting is that this app is going to listen for the state changes coming from AngularFire 2 and then use entity adapters to update the local data store. Currently, I've queried all the pizzas that have a status of cooking.

So if the status changes from anything other than cooking, it should be removed from our local data store. If we update the status from cooking to delivered, you'll see that it gets removed from the local data store and that action is triggered here in Redux DevTools. The key takeaway here is that you'll always know how your data is changing relative to the way you queried it from Firestore. Let's go ahead and set up the n g r x actions that make this possible. The first action is query.

Eventually, it's going to make a query to Firestore and listen to any changes that happened to that data. And from there, we're going to set up added, modified, and removed. It's important that you keep these names consistent because they're returned to us from AngularFire 2. I also wanna show you how to update data on a Firestore document. So we'll set up actions for update and success.

Each of these actions will have a class that implements the action interface and has a custom payload that we define in the constructor. The query action doesn't need a payload, But the added action will return an individual pizza object, so we can type that to our pizza interface. Then modified hide and removed will also follow the same exact pattern. They simply create a payload of a pizza object. The update action is a little more interesting.

It's going to take an entity ID as well as a partial piece of data that we wanna update on the interface. Normally, TypeScript wouldn't let us do this, but we can use The partial type with our pizza interface to update individual properties on the object. The success action is only used to show us when a successful Update operation has been completed, so there's no need to add a payload to it. Then the final step is to export all these actions as a single type. Now we're going to jump into the reducer and I'll go through the whole thing from top to bottom.

So first, we're gonna import the actions We just created as well as a few things here from NGRX, then we'll define our pizza interface, which just has an ID, a size and a status which can either be cooking or delivered. Then we can use this interface to initialize our adapter. This will give us access to a bunch of helper methods to update the state consistently. From there, we use entity state to extend the main state interface. This ensures that our data conforms to a specific format for entity.

And if you have some initial data you wanna set as the initial state, you would do that here, but for now I'm just going to leave it blank. Now we're ready to build the reducer function. It takes the old state as well as the action that's being dispatched, which will be one of our pizza actions. And then we'll set up the switch statement here And the first one we'll look for is added. So whenever we get a new item that's added, we're going to add 1 pizza to the state.

That will add one new pizza to the state and keep track of its ID and everything automatically. For modified, we'll call update 1, then pass it the entity ID as well as the changes that we wanna make. Then the same basic idea for removed, but this time we'll call remove 1. And it takes the ID as the argument. With just these three actions in the reducer, we can throw around all kinds of different asynchronous events while providing a ton of feedback about our local data store.

The last step is to create the selectors that allow us to slice various pieces of the state. That's done by calling create feature selector And then n g r x gives us a bunch of built in helper methods, or you can create your own to slice different pieces of the state. In this demo, we're only gonna be using select all. Now we're ready to build the n g r x effect. The effect will allow us to isolate asynchronous events, So we don't have to actually trigger those events from inside a component.

In other words, components should only dispatch events and select parts of the store. They shouldn't cause any asynchronous side effects on their own. We're also gonna be using the new loadable operators from RxJS 5 point 5. So the import syntax is slightly different as you see here. The first thing I'm going to do is inject the actions as well as the Angular Firestore library in the constructor.

The most important effect here is query, and that's going to make the query to Firestore for collection and handle the added, modified, removed events that come from that collection. So first, we call actions of type with the query action. That returns an observable, so we can pipe multiple RxJS operators here, which will make our code more readable than it has been in previous tutorials that I've shown you about NGRX The next step is to make a query to Firestore. So we do that by calling AngularFirestore collection, and then we're going to Only query the pizzas that have a status of cooking. Then to get an n g r x friendly observable from Firestore, we call state changes.

That returns an array of actions, so we'll map that down to each individual action by calling merge map. Then we can dispatch the correct action based on what's returned from Firestore. So we'll call pizza with the action type, which will be added, modified, or removed. And then the payload will be the actual data that we update on the local store. We want both the data and the document ID so we can map those together here in the object.

That's all there is to it. Your local data store will now stay in sync with the data in Firebase Airbase and you'll have a lot of flexibility for managing those changes. But we're not quite done yet. I still wanna set up one more effect so the user can manually update data in Firestore. This time we're going to listen to the update action and when that occurs we'll map it down to the data payload.

That has the document ID as well as the data that we want to update. From that point, we call switch map and then with the data that we wanna Update will make a reference to that pizza in Firestore. Then the update action is going to return a Promise, so we're going to create an observable from that Promise. To take care of that, you can do Observable from Promise and then make the update inside of it. And lastly, we'll map that down Onto the success action once that promise resolves successfully.

It also be a good idea to catch errors here and dispatch an error action, but I'm skipping that part for now. We're almost done at this point. We just need a component for the end user to interact with. We'll go ahead and import ngrxstore as well as the actions and reducer that we just created. Then our actual observable will be an array of pizzas.

The store is injected in the constructor and it's typed to our pizza interface. We'll make the initial query during n g on a net, but first, we'll select the slice of the store we want for our pizza's variable. After that, all we have to do is dispatch the query action. And our front end is going to have some buttons where the user can update the state of an individual pizza. The update pizza method is an event handler that will bind to a button click, and we can just dispatch the update action with the corresponding payload.

The HTML code is incredibly simple. We just loop over the array of pizzas, and then for each one, we'll add that update status button. Clicking this button will trigger an asynchronous write operation, which will update the pizza from a status of cooking to delivered. Now let's go into the app and take a closer look at what's actually happening here. The initial page load pulls the data from Firestore and then adds it to the state in the entity format.

If you look at the actions, we first have a query pizzas action and then we have 4 added events after that. And of course, that gives us 4 pizzas on the screen here as well. Now let's see what happens when we click the Update Status button. We get 3 actions here. First, the update And then it's removed from the local store, then update success after the actual update promise resolves.

So even though the pizza wasn't removed from Firestore, you still get the removed action because it was removed from the local store. You could use that state change to toggle a CSS class or show a Toast message or any other UI element you can Now let's take a look at one more thing. What happens if we update a property on a pizza from Firestore or any other client subscribing to this data? You'll see down here in DevTools, we get a modified action, which tells us that the data on the pizza was updated, but it still remains in our base query. The end result is that you now have a system that will detect changes in Firestore and tell you exactly how they affect your local NGRX store.

That's it for NGRX with AngularFire 2. If this video helped you, please like and subscribe. And if you wanna learn more every week, consider becoming a pro subscriber at angularfirebase.com. You'll get access to exclusive content, a free copy of my book, as well as a bunch of other resources designed to help you get your app off the ground. Thanks for watching, and I'll see you soon.
A few weeks ago, I showed you how to use NGRX entity adapters. Today, I'm going to build on this concept and show you how to use Firestore as a persistent back end data source. You might be aware that AngularFire version 5 has a new state changes method, which we're going to take advantage of in this episode. It makes it possible to keep track of when documents are added, modified or removed. If you want an example of how this might be used, look no further than the Firebase console itself. If we add a new value to the database, you'll see It flashes green for a split second. And, the document itself is modified so it flashes orange. If we remove the property, then it flashes red. The Firestore web console happens to be built with NGRX, which I learned by watching Angular Air episode 135. So make sure to check that out as well. If you're new here, click the subscribe button and follow along with the source code at angularfirebase.com. To get started, I'm going to first show you how we have this App setup based on the previous video. Starting with the app module, the main change we made is we installed AngularFire 2 along with Firestore. I'm also including the ngrx effects module and in the root, just passing it an empty array. If you're lost at this point, Make sure to go back and watch the n g r x entity video. From there, I'm going to go into our pizza feature module And I have a new file called pizza effects that we're going to create later. We also import the effects module here but call for feature and pass it the pizza effects file. The actual app we're building is just a collection of pizzas, and the user has the ability to asynchronously update them from a status of cooking to delivered. The thing that's interesting is that this app is going to listen for the state changes coming from AngularFire 2 and then use entity adapters to update the local data store. Currently, I've queried all the pizzas that have a status of cooking. So if the status changes from anything other than cooking, it should be removed from our local data store. If we update the status from cooking to delivered, you'll see that it gets removed from the local data store and that action is triggered here in Redux DevTools.
The key takeaway here is that you'll always know how your data is changing relative to the way you queried it from Firestore. Let's go ahead and set up the n g r x actions that make this possible. The first action is query. Eventually, it's going to make a query to Firestore and listen to any changes that happened to that data. And from there, we're going to set up added, modified, and removed. It's important that you keep these names consistent because they're returned to us from AngularFire 2.
data
databases
data management
I also wanna show you how to update data on a Firestore document. So we'll set up actions for update and success. Each of these actions will have a class that implements the action interface and has a custom payload that we define in the constructor. The query action doesn't need a payload, But the added action will return an individual pizza object, so we can type that to our pizza interface. Then modified hide and removed will also follow the same exact pattern. They simply create a payload of a pizza object. The update action is a little more interesting. It's going to take an entity ID as well as a partial piece of data that we wanna update on the interface. Normally, TypeScript wouldn't let us do this, but we can use The partial type with our pizza interface to update individual properties on the object.
The success action is only used to show us when a successful Update operation has been completed, so there's no need to add a payload to it. Then the final step is to export all these actions as a single type. Now we're going to jump into the reducer and I'll go through the whole thing from top to bottom.
operations
So first, we're gonna import the actions We just created as well as a few things here from NGRX, then we'll define our pizza interface, which just has an ID, a size and a status which can either be cooking or delivered. Then we can use this interface to initialize our adapter. This will give us access to a bunch of helper methods to update the state consistently. From there, we use entity state to extend the main state interface. This ensures that our data conforms to a specific format for entity. And if you have some initial data you wanna set as the initial state, you would do that here, but for now I'm just going to leave it blank. Now we're ready to build the reducer function. It takes the old state as well as the action that's being dispatched, which will be one of our pizza actions. And then we'll set up the switch statement here And the first one we'll look for is added. So whenever we get a new item that's added, we're going to add 1 pizza to the state. That will add one new pizza to the state and keep track of its ID and everything automatically. For modified, we'll call update 1, then pass it the entity ID as well as the changes that we wanna make. Then the same basic idea for removed, but this time we'll call remove 1. And it takes the ID as the argument. With just these three actions in the reducer, we can throw around all kinds of different asynchronous events while providing a ton of feedback about our local data store. The last step is to create the selectors that allow us to slice various pieces of the state. That's done by calling create feature selector And then n g r x gives us a bunch of built in helper methods, or you can create your own to slice different pieces of the state. In this demo, we're only gonna be using select all. Now we're ready to build the n g r x effect. The effect will allow us to isolate asynchronous events, So we don't have to actually trigger those events from inside a component. In other words, components should only dispatch events and select parts of the store. They shouldn't cause any asynchronous side effects on their own. We're also gonna be using the new loadable operators from RxJS 5 point 5. So the import syntax is slightly different as you see here. The first thing I'm going to do is inject the actions as well as the Angular Firestore library in the constructor.
The most important effect here is query, and that's going to make the query to Firestore for collection and handle the added, modified, removed events that come from that collection. So first, we call actions of type with the query action. That returns an observable, so we can pipe multiple RxJS operators here, which will make our code more readable than it has been in previous tutorials that I've shown you about NGRX The next step is to make a query to Firestore.
databases
So we do that by calling AngularFirestore collection, and then we're going to Only query the pizzas that have a status of cooking. Then to get an n g r x friendly observable from Firestore, we call state changes.
That returns an array of actions, so we'll map that down to each individual action by calling merge map. Then we can dispatch the correct action based on what's returned from Firestore. So we'll call pizza with the action type, which will be added, modified, or removed. And then the payload will be the actual data that we update on the local store.
operations
We want both the data and the document ID so we can map those together here in the object. That's all there is to it. Your local data store will now stay in sync with the data in Firebase Airbase and you'll have a lot of flexibility for managing those changes.
data management
databases
data
data analysis
But we're not quite done yet. I still wanna set up one more effect so the user can manually update data in Firestore. This time we're going to listen to the update action and when that occurs we'll map it down to the data payload. That has the document ID as well as the data that we want to update. From that point, we call switch map and then with the data that we wanna Update will make a reference to that pizza in Firestore. Then the update action is going to return a Promise, so we're going to create an observable from that Promise. To take care of that, you can do Observable from Promise and then make the update inside of it.
And lastly, we'll map that down Onto the success action once that promise resolves successfully. It also be a good idea to catch errors here and dispatch an error action, but I'm skipping that part for now. We're almost done at this point. We just need a component for the end user to interact with. We'll go ahead and import ngrxstore as well as the actions and reducer that we just created. Then our actual observable will be an array of pizzas. The store is injected in the constructor and it's typed to our pizza interface. We'll make the initial query during n g on a net, but first, we'll select the slice of the store we want for our pizza's variable.
operations
visualization
programming
After that, all we have to do is dispatch the query action. And our front end is going to have some buttons where the user can update the state of an individual pizza. The update pizza method is an event handler that will bind to a button click, and we can just dispatch the update action with the corresponding payload. The HTML code is incredibly simple. We just loop over the array of pizzas, and then for each one, we'll add that update status button. Clicking this button will trigger an asynchronous write operation, which will update the pizza from a status of cooking to delivered. Now let's go into the app and take a closer look at what's actually happening here. The initial page load pulls the data from Firestore and then adds it to the state in the entity format. If you look at the actions, we first have a query pizzas action and then we have 4 added events after that. And of course, that gives us 4 pizzas on the screen here as well. Now let's see what happens when we click the Update Status button. We get 3 actions here. First, the update And then it's removed from the local store, then update success after the actual update promise resolves. So even though the pizza wasn't removed from Firestore, you still get the removed action because it was removed from the local store. You could use that state change to toggle a CSS class or show a Toast message or any other UI element you can Now let's take a look at one more thing. What happens if we update a property on a pizza from Firestore or any other client subscribing to this data? You'll see down here in DevTools, we get a modified action, which tells us that the data on the pizza was updated, but it still remains in our base query. The end result is that you now have a system that will detect changes in Firestore and tell you exactly how they affect your local NGRX store.
That's it for NGRX with AngularFire 2. If this video helped you, please like and subscribe. And if you wanna learn more every week, consider becoming a pro subscriber at angularfirebase.com. You'll get access to exclusive content, a free copy of my book, as well as a bunch of other resources designed to help you get your app off the ground. Thanks for watching, and I'll see you soon.
books
publishing
copyright
youtube
seasons
websites
A few weeks ago, I showed you how to use NGRX entity adapters. Today, I'm going to build on this concept and show you how to use Firestore as a persistent back end data source. You might be aware that AngularFire version 5 has a new state changes method, which we're going to take advantage of in this episode. It makes it possible to keep track of when documents are added, modified or removed. If you want an example of how this might be used, look no further than the Firebase console itself. If we add a new value to the database, you'll see It flashes green for a split second. And, the document itself is modified so it flashes orange. If we remove the property, then it flashes red. The Firestore web console happens to be built with NGRX, which I learned by watching Angular Air episode 135. So make sure to check that out as well. If you're new here, click the subscribe button and follow along with the source code at angularfirebase.com. To get started, I'm going to first show you how we have this App setup based on the previous video. Starting with the app module, the main change we made is we installed AngularFire 2 along with Firestore. I'm also including the ngrx effects module and in the root, just passing it an empty array. If you're lost at this point, Make sure to go back and watch the n g r x entity video. From there, I'm going to go into our pizza feature module And I have a new file called pizza effects that we're going to create later. We also import the effects module here but call for feature and pass it the pizza effects file. The actual app we're building is just a collection of pizzas, and the user has the ability to asynchronously update them from a status of cooking to delivered. The thing that's interesting is that this app is going to listen for the state changes coming from AngularFire 2 and then use entity adapters to update the local data store. Currently, I've queried all the pizzas that have a status of cooking. So if the status changes from anything other than cooking, it should be removed from our local data store. If we update the status from cooking to delivered, you'll see that it gets removed from the local data store and that action is triggered here in Redux DevTools. The key takeaway here is that you'll always know how your data is changing relative to the way you queried it from Firestore. Let's go ahead and set up the n g r x actions that make this possible. The first action is query. Eventually, it's going to make a query to Firestore and listen to any changes that happened to that data. And from there, we're going to set up added, modified, and removed. It's important that you keep these names consistent because they're returned to us from AngularFire 2. I also wanna show you how to update data on a Firestore document. So we'll set up actions for update and success. Each of these actions will have a class that implements the action interface and has a custom payload that we define in the constructor. The query action doesn't need a payload, But the added action will return an individual pizza object, so we can type that to our pizza interface. Then modified hide and removed will also follow the same exact pattern. They simply create a payload of a pizza object. The update action is a little more interesting. It's going to take an entity ID as well as a partial piece of data that we wanna update on the interface. Normally, TypeScript wouldn't let us do this, but we can use The partial type with our pizza interface to update individual properties on the object. The success action is only used to show us when a successful Update operation has been completed, so there's no need to add a payload to it. Then the final step is to export all these actions as a single type. Now we're going to jump into the reducer and I'll go through the whole thing from top to bottom. So first, we're gonna import the actions We just created as well as a few things here from NGRX, then we'll define our pizza interface, which just has an ID, a size and a status which can either be cooking or delivered. Then we can use this interface to initialize our adapter. This will give us access to a bunch of helper methods to update the state consistently. From there, we use entity state to extend the main state interface. This ensures that our data conforms to a specific format for entity. And if you have some initial data you wanna set as the initial state, you would do that here, but for now I'm just going to leave it blank. Now we're ready to build the reducer function. It takes the old state as well as the action that's being dispatched, which will be one of our pizza actions. And then we'll set up the switch statement here And the first one we'll look for is added. So whenever we get a new item that's added, we're going to add 1 pizza to the state. That will add one new pizza to the state and keep track of its ID and everything automatically. For modified, we'll call update 1, then pass it the entity ID as well as the changes that we wanna make. Then the same basic idea for removed, but this time we'll call remove 1. And it takes the ID as the argument. With just these three actions in the reducer, we can throw around all kinds of different asynchronous events while providing a ton of feedback about our local data store. The last step is to create the selectors that allow us to slice various pieces of the state. That's done by calling create feature selector And then n g r x gives us a bunch of built in helper methods, or you can create your own to slice different pieces of the state. In this demo, we're only gonna be using select all. Now we're ready to build the n g r x effect. The effect will allow us to isolate asynchronous events, So we don't have to actually trigger those events from inside a component. In other words, components should only dispatch events and select parts of the store. They shouldn't cause any asynchronous side effects on their own. We're also gonna be using the new loadable operators from RxJS 5 point 5. So the import syntax is slightly different as you see here. The first thing I'm going to do is inject the actions as well as the Angular Firestore library in the constructor. The most important effect here is query, and that's going to make the query to Firestore for collection and handle the added, modified, removed events that come from that collection. So first, we call actions of type with the query action. That returns an observable, so we can pipe multiple RxJS operators here, which will make our code more readable than it has been in previous tutorials that I've shown you about NGRX The next step is to make a query to Firestore. So we do that by calling AngularFirestore collection, and then we're going to Only query the pizzas that have a status of cooking. Then to get an n g r x friendly observable from Firestore, we call state changes. That returns an array of actions, so we'll map that down to each individual action by calling merge map. Then we can dispatch the correct action based on what's returned from Firestore. So we'll call pizza with the action type, which will be added, modified, or removed. And then the payload will be the actual data that we update on the local store. We want both the data and the document ID so we can map those together here in the object. That's all there is to it. Your local data store will now stay in sync with the data in Firebase Airbase and you'll have a lot of flexibility for managing those changes. But we're not quite done yet. I still wanna set up one more effect so the user can manually update data in Firestore. This time we're going to listen to the update action and when that occurs we'll map it down to the data payload. That has the document ID as well as the data that we want to update. From that point, we call switch map and then with the data that we wanna Update will make a reference to that pizza in Firestore. Then the update action is going to return a Promise, so we're going to create an observable from that Promise. To take care of that, you can do Observable from Promise and then make the update inside of it. And lastly, we'll map that down Onto the success action once that promise resolves successfully. It also be a good idea to catch errors here and dispatch an error action, but I'm skipping that part for now. We're almost done at this point. We just need a component for the end user to interact with. We'll go ahead and import ngrxstore as well as the actions and reducer that we just created. Then our actual observable will be an array of pizzas. The store is injected in the constructor and it's typed to our pizza interface. We'll make the initial query during n g on a net, but first, we'll select the slice of the store we want for our pizza's variable. After that, all we have to do is dispatch the query action. And our front end is going to have some buttons where the user can update the state of an individual pizza. The update pizza method is an event handler that will bind to a button click, and we can just dispatch the update action with the corresponding payload. The HTML code is incredibly simple. We just loop over the array of pizzas, and then for each one, we'll add that update status button. Clicking this button will trigger an asynchronous write operation, which will update the pizza from a status of cooking to delivered. Now let's go into the app and take a closer look at what's actually happening here. The initial page load pulls the data from Firestore and then adds it to the state in the entity format. If you look at the actions, we first have a query pizzas action and then we have 4 added events after that. And of course, that gives us 4 pizzas on the screen here as well. Now let's see what happens when we click the Update Status button. We get 3 actions here. First, the update And then it's removed from the local store, then update success after the actual update promise resolves. So even though the pizza wasn't removed from Firestore, you still get the removed action because it was removed from the local store. You could use that state change to toggle a CSS class or show a Toast message or any other UI element you can Now let's take a look at one more thing. What happens if we update a property on a pizza from Firestore or any other client subscribing to this data? You'll see down here in DevTools, we get a modified action, which tells us that the data on the pizza was updated, but it still remains in our base query. The end result is that you now have a system that will detect changes in Firestore and tell you exactly how they affect your local NGRX store. That's it for NGRX with AngularFire 2. If this video helped you, please like and subscribe. And if you wanna learn more every week, consider becoming a pro subscriber at angularfirebase.com. You'll get access to exclusive content, a free copy of my book, as well as a bunch of other resources designed to help you get your app off the ground. Thanks for watching, and I'll see you soon.
A
a
few
few
weeks
weeks
ago,
ago
I
i
showed
showed
you
you
how
how
to
to
use
use
NGRX
ngrx
entity
entity
adapters.
adapters
Today,
today
I'm
i'm
going
going
to
to
build
build
on
on
this
this
concept
concept
and
and
show
show
you
you
how
how
to
to
use
use
Firestore
firestore
as
as
a
a
persistent
persistent
back
back
end
end
data
data
source.
source
You
you
might
might
be
be
aware
aware
that
that
AngularFire
angularfire
version
version
5
5
has
has
a
a
new
new
state
state
changes
changes
method,
method
which
which
we're
we're
going
going
to
to
take
take
advantage
advantage
of
of
in
in
this
this
episode.
episode
It
it
makes
makes
it
it
possible
possible
to
to
keep
keep
track
track
of
of
when
when
documents
documents
are
are
added,
added
modified
modified
or
or
removed.
removed
If
if
you
you
want
want
an
an
example
example
of
of
how
how
this
this
might
might
be
be
used,
used
look
look
no
no
further
further
than
than
the
the
Firebase
firebase
console
console
itself.
itself
If
if
we
we
add
add
a
a
new
new
value
value
to
to
the
the
database,
database
you'll
you'll
see
see
It
it
flashes
flashes
green
green
for
for
a
a
split
split
second.
second
And,
and
the
the
document
document
itself
itself
is
is
modified
modified
so
so
it
it
flashes
flashes
orange.
orange
If
if
we
we
remove
remove
the
the
property,
property
then
then
it
it
flashes
flashes
red.
red
The
the
Firestore
firestore
web
web
console
console
happens
happens
to
to
be
be
built
built
with
with
NGRX,
ngrx
which
which
I
i
learned
learned
by
by
watching
watching
Angular
angular
Air
air
episode
episode
135.
135
So
so
make
make
sure
sure
to
to
check
check
that
that
out
out
as
as
well.
well
If
if
you're
you're
new
new
here,
here
click
click
the
the
subscribe
subscribe
button
button
and
and
follow
follow
along
along
with
with
the
the
source
source
code
code
at
at
angularfirebase.com.
angularfirebase.com
To
to
get
get
started,
started
I'm
i'm
going
going
to
to
first
first
show
show
you
you
how
how
we
we
have
have
this
this
App
app
setup
setup
based
based
on
on
the
the
previous
previous
video.
video
Starting
starting
with
with
the
the
app
app
module,
module
the
the
main
main
change
change
we
we
made
made
is
is
we
we
installed
installed
AngularFire
angularfire
2
2
along
along
with
with
Firestore.
firestore
I'm
i'm
also
also
including
including
the
the
ngrx
ngrx
effects
effects
module
module
and
and
in
in
the
the
root,
root
just
just
passing
passing
it
it
an
an
empty
empty
array.
array
If
if
you're
you're
lost
lost
at
at
this
this
point,
point
Make
make
sure
sure
to
to
go
go
back
back
and
and
watch
watch
the
the
n
n
g
g
r
r
x
x
entity
entity
video.
video
From
from
there,
there
I'm
i'm
going
going
to
to
go
go
into
into
our
our
pizza
pizza
feature
feature
module
module
And
and
I
i
have
have
a
a
new
new
file
file
called
called
pizza
pizza
effects
effects
that
that
we're
we're
going
going
to
to
create
create
later.
later
We
we
also
also
import
import
the
the
effects
effects
module
module
here
here
but
but
call
call
for
for
feature
feature
and
and
pass
pass
it
it
the
the
pizza
pizza
effects
effects
file.
file
The
the
actual
actual
app
app
we're
we're
building
building
is
is
just
just
a
a
collection
collection
of
of
pizzas,
pizzas
and
and
the
the
user
user
has
has
the
the
ability
ability
to
to
asynchronously
asynchronously
update
update
them
them
from
from
a
a
status
status
of
of
cooking
cooking
to
to
delivered.
delivered
The
the
thing
thing
that's
that's
interesting
interesting
is
is
that
that
this
this
app
app
is
is
going
going
to
to
listen
listen
for
for
the
the
state
state
changes
changes
coming
coming
from
from
AngularFire
angularfire
2
2
and
and
then
then
use
use
entity
entity
adapters
adapters
to
to
update
update
the
the
local
local
data
data
store.
store
Currently,
currently
I've
i've
queried
queried
all
all
the
the
pizzas
pizzas
that
that
have
have
a
a
status
status
of
of
cooking.
cooking
So
so
if
if
the
the
status
status
changes
changes
from
from
anything
anything
other
other
than
than
cooking,
cooking
it
it
should
should
be
be
removed
removed
from
from
our
our
local
local
data
data
store.
store
If
if
we
we
update
update
the
the
status
status
from
from
cooking
cooking
to
to
delivered,
delivered
you'll
you'll
see
see
that
that
it
it
gets
gets
removed
removed
from
from
the
the
local
local
data
data
store
store
and
and
that
that
action
action
is
is
triggered
triggered
here
here
in
in
Redux
redux
DevTools.
devtools
The
the
key
key
takeaway
takeaway
here
here
is
is
that
that
you'll
you'll
always
always
know
know
how
how
your
your
data
data
is
is
changing
changing
relative
relative
to
to
the
the
way
way
you
you
queried
queried
it
it
from
from
Firestore.
firestore
Let's
let's
go
go
ahead
ahead
and
and
set
set
up
up
the
the
n
n
g
g
r
r
x
x
actions
actions
that
that
make
make
this
this
possible.
possible
The
the
first
first
action
action
is
is
query.
query
Eventually,
eventually
it's
it's
going
going
to
to
make
make
a
a
query
query
to
to
Firestore
firestore
and
and
listen
listen
to
to
any
any
changes
changes
that
that
happened
happened
to
to
that
that
data.
data
And
and
from
from
there,
there
we're
we're
going
going
to
to
set
set
up
up
added,
added
modified,
modified
and
and
removed.
removed
It's
it's
important
important
that
that
you
you
keep
keep
these
these
names
names
consistent
consistent
because
because
they're
they're
returned
returned
to
to
us
us
from
from
AngularFire
angularfire
2.
2
I
i
also
also
wanna
wanna
show
show
you
you
how
how
to
to
update
update
data
data
on
on
a
a
Firestore
firestore
document.
document
So
so
we'll
we'll
set
set
up
up
actions
actions
for
for
update
update
and
and
success.
success
Each
each
of
of
these
these
actions
actions
will
will
have
have
a
a
class
class
that
that
implements
implements
the
the
action
action
interface
interface
and
and
has
has
a
a
custom
custom
payload
payload
that
that
we
we
define
define
in
in
the
the
constructor.
constructor
The
the
query
query
action
action
doesn't
doesn't
need
need
a
a
payload,
payload
But
but
the
the
added
added
action
action
will
will
return
return
an
an
individual
individual
pizza
pizza
object,
object
so
so
we
we
can
can
type
type
that
that
to
to
our
our
pizza
pizza
interface.
interface
Then
then
modified
modified
hide
hide
and
and
removed
removed
will
will
also
also
follow
follow
the
the
same
same
exact
exact
pattern.
pattern
They
they
simply
simply
create
create
a
a
payload
payload
of
of
a
a
pizza
pizza
object.
object
The
the
update
update
action
action
is
is
a
a
little
little
more
more
interesting.
interesting
It's
it's
going
going
to
to
take
take
an
an
entity
entity
ID
id
as
as
well
well
as
as
a
a
partial
partial
piece
piece
of
of
data
data
that
that
we
we
wanna
wanna
update
update
on
on
the
the
interface.
interface
Normally,
normally
TypeScript
typescript
wouldn't
wouldn't
let
let
us
us
do
do
this,
this
but
but
we
we
can
can
use
use
The
the
partial
partial
type
type
with
with
our
our
pizza
pizza
interface
interface
to
to
update
update
individual
individual
properties
properties
on
on
the
the
object.
object
The
the
success
success
action
action
is
is
only
only
used
used
to
to
show
show
us
us
when
when
a
a
successful
successful
Update
update
operation
operation
has
has
been
been
completed,
completed
so
so
there's
there's
no
no
need
need
to
to
add
add
a
a
payload
payload
to
to
it.
it
Then
then
the
the
final
final
step
step
is
is
to
to
export
export
all
all
these
these
actions
actions
as
as
a
a
single
single
type.
type
Now
now
we're
we're
going
going
to
to
jump
jump
into
into
the
the
reducer
reducer
and
and
I'll
i'll
go
go
through
through
the
the
whole
whole
thing
thing
from
from
top
top
to
to
bottom.
bottom
So
so
first,
first
we're
we're
gonna
gonna
import
import
the
the
actions
actions
We
we
just
just
created
created
as
as
well
well
as
as
a
a
few
few
things
things
here
here
from
from
NGRX,
ngrx
then
then
we'll
we'll
define
define
our
our
pizza
pizza
interface,
interface
which
which
just
just
has
has
an
an
ID,
id
a
a
size
size
and
and
a
a
status
status
which
which
can
can
either
either
be
be
cooking
cooking
or
or
delivered.
delivered
Then
then
we
we
can
can
use
use
this
this
interface
interface
to
to
initialize
initialize
our
our
adapter.
adapter
This
this
will
will
give
give
us
us
access
access
to
to
a
a
bunch
bunch
of
of
helper
helper
methods
methods
to
to
update
update
the
the
state
state
consistently.
consistently
From
from
there,
there
we
we
use
use
entity
entity
state
state
to
to
extend
extend
the
the
main
main
state
state
interface.
interface
This
this
ensures
ensures
that
that
our
our
data
data
conforms
conforms
to
to
a
a
specific
specific
format
format
for
for
entity.
entity
And
and
if
if
you
you
have
have
some
some
initial
initial
data
data
you
you
wanna
wanna
set
set
as
as
the
the
initial
initial
state,
state
you
you
would
would
do
do
that
that
here,
here
but
but
for
for
now
now
I'm
i'm
just
just
going
going
to
to
leave
leave
it
it
blank.
blank
Now
now
we're
we're
ready
ready
to
to
build
build
the
the
reducer
reducer
function.
function
It
it
takes
takes
the
the
old
old
state
state
as
as
well
well
as
as
the
the
action
action
that's
that's
being
being
dispatched,
dispatched
which
which
will
will
be
be
one
one
of
of
our
our
pizza
pizza
actions.
actions
And
and
then
then
we'll
we'll
set
set
up
up
the
the
switch
switch
statement
statement
here
here
And
and
the
the
first
first
one
one
we'll
we'll
look
look
for
for
is
is
added.
added
So
so
whenever
whenever
we
we
get
get
a
a
new
new
item
item
that's
that's
added,
added
we're
we're
going
going
to
to
add
add
1
1
pizza
pizza
to
to
the
the
state.
state
That
that
will
will
add
add
one
one
new
new
pizza
pizza
to
to
the
the
state
state
and
and
keep
keep
track
track
of
of
its
its
ID
id
and
and
everything
everything
automatically.
automatically
For
for
modified,
modified
we'll
we'll
call
call
update
update
1,
1
then
then
pass
pass
it
it
the
the
entity
entity
ID
id
as
as
well
well
as
as
the
the
changes
changes
that
that
we
we
wanna
wanna
make.
make
Then
then
the
the
same
same
basic
basic
idea
idea
for
for
removed,
removed
but
but
this
this
time
time
we'll
we'll
call
call
remove
remove
1.
1
And
and
it
it
takes
takes
the
the
ID
id
as
as
the
the
argument.
argument
With
with
just
just
these
these
three
three
actions
actions
in
in
the
the
reducer,
reducer
we
we
can
can
throw
throw
around
around
all
all
kinds
kinds
of
of
different
different
asynchronous
asynchronous
events
events
while
while
providing
providing
a
a
ton
ton
of
of
feedback
feedback
about
about
our
our
local
local
data
data
store.
store
The
the
last
last
step
step
is
is
to
to
create
create
the
the
selectors
selectors
that
that
allow
allow
us
us
to
to
slice
slice
various
various
pieces
pieces
of
of
the
the
state.
state
That's
that's
done
done
by
by
calling
calling
create
create
feature
feature
selector
selector
And
and
then
then
n
n
g
g
r
r
x
x
gives
gives
us
us
a
a
bunch
bunch
of
of
built
built
in
in
helper
helper
methods,
methods
or
or
you
you
can
can
create
create
your
your
own
own
to
to
slice
slice
different
different
pieces
pieces
of
of
the
the
state.
state
In
in
this
this
demo,
demo
we're
we're
only
only
gonna
gonna
be
be
using
using
select
select
all.
all
Now
now
we're
we're
ready
ready
to
to
build
build
the
the
n
n
g
g
r
r
x
x
effect.
effect
The
the
effect
effect
will
will
allow
allow
us
us
to
to
isolate
isolate
asynchronous
asynchronous
events,
events
So
so
we
we
don't
don't
have
have
to
to
actually
actually
trigger
trigger
those
those
events
events
from
from
inside
inside
a
a
component.
component
In
in
other
other
words,
words
components
components
should
should
only
only
dispatch
dispatch
events
events
and
and
select
select
parts
parts
of
of
the
the
store.
store
They
they
shouldn't
shouldn't
cause
cause
any
any
asynchronous
asynchronous
side
side
effects
effects
on
on
their
their
own.
own
We're
we're
also
also
gonna
gonna
be
be
using
using
the
the
new
new
loadable
loadable
operators
operators
from
from
RxJS
rxjs
5
5
point
point
5.
5
So
so
the
the
import
import
syntax
syntax
is
is
slightly
slightly
different
different
as
as
you
you
see
see
here.
here
The
the
first
first
thing
thing
I'm
i'm
going
going
to
to
do
do
is
is
inject
inject
the
the
actions
actions
as
as
well
well
as
as
the
the
Angular
angular
Firestore
firestore
library
library
in
in
the
the
constructor.
constructor
The
the
most
most
important
important
effect
effect
here
here
is
is
query,
query
and
and
that's
that's
going
going
to
to
make
make
the
the
query
query
to
to
Firestore
firestore
for
for
collection
collection
and
and
handle
handle
the
the
added,
added
modified,
modified
removed
removed
events
events
that
that
come
come
from
from
that
that
collection.
collection
So
so
first,
first
we
we
call
call
actions
actions
of
of
type
type
with
with
the
the
query
query
action.
action
That
that
returns
returns
an
an
observable,
observable
so
so
we
we
can
can
pipe
pipe
multiple
multiple
RxJS
rxjs
operators
operators
here,
here
which
which
will
will
make
make
our
our
code
code
more
more
readable
readable
than
than
it
it
has
has
been
been
in
in
previous
previous
tutorials
tutorials
that
that
I've
i've
shown
shown
you
you
about
about
NGRX
ngrx
The
the
next
next
step
step
is
is
to
to
make
make
a
a
query
query
to
to
Firestore.
firestore
So
so
we
we
do
do
that
that
by
by
calling
calling
AngularFirestore
angularfirestore
collection,
collection
and
and
then
then
we're
we're
going
going
to
to
Only
only
query
query
the
the
pizzas
pizzas
that
that
have
have
a
a
status
status
of
of
cooking.
cooking
Then
then
to
to
get
get
an
an
n
n
g
g
r
r
x
x
friendly
friendly
observable
observable
from
from
Firestore,
firestore
we
we
call
call
state
state
changes.
changes
That
that
returns
returns
an
an
array
array
of
of
actions,
actions
so
so
we'll
we'll
map
map
that
that
down
down
to
to
each
each
individual
individual
action
action
by
by
calling
calling
merge
merge
map.
map
Then
then
we
we
can
can
dispatch
dispatch
the
the
correct
correct
action
action
based
based
on
on
what's
what's
returned
returned
from
from
Firestore.
firestore
So
so
we'll
we'll
call
call
pizza
pizza
with
with
the
the
action
action
type,
type
which
which
will
will
be
be
added,
added
modified,
modified
or
or
removed.
removed
And
and
then
then
the
the
payload
payload
will
will
be
be
the
the
actual
actual
data
data
that
that
we
we
update
update
on
on
the
the
local
local
store.
store
We
we
want
want
both
both
the
the
data
data
and
and
the
the
document
document
ID
id
so
so
we
we
can
can
map
map
those
those
together
together
here
here
in
in
the
the
object.
object
That's
that's
all
all
there
there
is
is
to
to
it.
it
Your
your
local
local
data
data
store
store
will
will
now
now
stay
stay
in
in
sync
sync
with
with
the
the
data
data
in
in
Firebase
firebase
Airbase
airbase
and
and
you'll
you'll
have
have
a
a
lot
lot
of
of
flexibility
flexibility
for
for
managing
managing
those
those
changes.
changes
But
but
we're
we're
not
not
quite
quite
done
done
yet.
yet
I
i
still
still
wanna
wanna
set
set
up
up
one
one
more
more
effect
effect
so
so
the
the
user
user
can
can
manually
manually
update
update
data
data
in
in
Firestore.
firestore
This
this
time
time
we're
we're
going
going
to
to
listen
listen
to
to
the
the
update
update
action
action
and
and
when
when
that
that
occurs
occurs
we'll
we'll
map
map
it
it
down
down
to
to
the
the
data
data
payload.
payload
That
that
has
has
the
the
document
document
ID
id
as
as
well
well
as
as
the
the
data
data
that
that
we
we
want
want
to
to
update.
update
From
from
that
that
point,
point
we
we
call
call
switch
switch
map
map
and
and
then
then
with
with
the
the
data
data
that
that
we
we
wanna
wanna
Update
update
will
will
make
make
a
a
reference
reference
to
to
that
that
pizza
pizza
in
in
Firestore.
firestore
Then
then
the
the
update
update
action
action
is
is
going
going
to
to
return
return
a
a
Promise,
promise
so
so
we're
we're
going
going
to
to
create
create
an
an
observable
observable
from
from
that
that
Promise.
promise
To
to
take
take
care
care
of
of
that,
that
you
you
can
can
do
do
Observable
observable
from
from
Promise
promise
and
and
then
then
make
make
the
the
update
update
inside
inside
of
of
it.
it
And
and
lastly,
lastly
we'll
we'll
map
map
that
that
down
down
Onto
onto
the
the
success
success
action
action
once
once
that
that
promise
promise
resolves
resolves
successfully.
successfully
It
it
also
also
be
be
a
a
good
good
idea
idea
to
to
catch
catch
errors
errors
here
here
and
and
dispatch
dispatch
an
an
error
error
action,
action
but
but
I'm
i'm
skipping
skipping
that
that
part
part
for
for
now.
now
We're
we're
almost
almost
done
done
at
at
this
this
point.
point
We
we
just
just
need
need
a
a
component
component
for
for
the
the
end
end
user
user
to
to
interact
interact
with.
with
We'll
we'll
go
go
ahead
ahead
and
and
import
import
ngrxstore
ngrxstore
as
as
well
well
as
as
the
the
actions
actions
and
and
reducer
reducer
that
that
we
we
just
just
created.
created
Then
then
our
our
actual
actual
observable
observable
will
will
be
be
an
an
array
array
of
of
pizzas.
pizzas
The
the
store
store
is
is
injected
injected
in
in
the
the
constructor
constructor
and
and
it's
it's
typed
typed
to
to
our
our
pizza
pizza
interface.
interface
We'll
we'll
make
make
the
the
initial
initial
query
query
during
during
n
n
g
g
on
on
a
a
net,
net
but
but
first,
first
we'll
we'll
select
select
the
the
slice
slice
of
of
the
the
store
store
we
we
want
want
for
for
our
our
pizza's
pizza's
variable.
variable
After
after
that,
that
all
all
we
we
have
have
to
to
do
do
is
is
dispatch
dispatch
the
the
query
query
action.
action
And
and
our
our
front
front
end
end
is
is
going
going
to
to
have
have
some
some
buttons
buttons
where
where
the
the
user
user
can
can
update
update
the
the
state
state
of
of
an
an
individual
individual
pizza.
pizza
The
the
update
update
pizza
pizza
method
method
is
is
an
an
event
event
handler
handler
that
that
will
will
bind
bind
to
to
a
a
button
button
click,
click
and
and
we
we
can
can
just
just
dispatch
dispatch
the
the
update
update
action
action
with
with
the
the
corresponding
corresponding
payload.
payload
The
the
HTML
html
code
code
is
is
incredibly
incredibly
simple.
simple
We
we
just
just
loop
loop
over
over
the
the
array
array
of
of
pizzas,
pizzas
and
and
then
then
for
for
each
each
one,
one
we'll
we'll
add
add
that
that
update
update
status
status
button.
button
Clicking
clicking
this
this
button
button
will
will
trigger
trigger
an
an
asynchronous
asynchronous
write
write
operation,
operation
which
which
will
will
update
update
the
the
pizza
pizza
from
from
a
a
status
status
of
of
cooking
cooking
to
to
delivered.
delivered
Now
now
let's
let's
go
go
into
into
the
the
app
app
and
and
take
take
a
a
closer
closer
look
look
at
at
what's
what's
actually
actually
happening
happening
here.
here
The
the
initial
initial
page
page
load
load
pulls
pulls
the
the
data
data
from
from
Firestore
firestore
and
and
then
then
adds
adds
it
it
to
to
the
the
state
state
in
in
the
the
entity
entity
format.
format
If
if
you
you
look
look
at
at
the
the
actions,
actions
we
we
first
first
have
have
a
a
query
query
pizzas
pizzas
action
action
and
and
then
then
we
we
have
have
4
4
added
added
events
events
after
after
that.
that
And
and
of
of
course,
course
that
that
gives
gives
us
us
4
4
pizzas
pizzas
on
on
the
the
screen
screen
here
here
as
as
well.
well
Now
now
let's
let's
see
see
what
what
happens
happens
when
when
we
we
click
click
the
the
Update
update
Status
status
button.
button
We
we
get
get
3
3
actions
actions
here.
here
First,
first
the
the
update
update
And
and
then
then
it's
it's
removed
removed
from
from
the
the
local
local
store,
store
then
then
update
update
success
success
after
after
the
the
actual
actual
update
update
promise
promise
resolves.
resolves
So
so
even
even
though
though
the
the
pizza
pizza
wasn't
wasn't
removed
removed
from
from
Firestore,
firestore
you
you
still
still
get
get
the
the
removed
removed
action
action
because
because
it
it
was
was
removed
removed
from
from
the
the
local
local
store.
store
You
you
could
could
use
use
that
that
state
state
change
change
to
to
toggle
toggle
a
a
CSS
css
class
class
or
or
show
show
a
a
Toast
toast
message
message
or
or
any
any
other
other
UI
ui
element
element
you
you
can
can
Now
now
let's
let's
take
take
a
a
look
look
at
at
one
one
more
more
thing.
thing
What
what
happens
happens
if
if
we
we
update
update
a
a
property
property
on
on
a
a
pizza
pizza
from
from
Firestore
firestore
or
or
any
any
other
other
client
client
subscribing
subscribing
to
to
this
this
data?
data
You'll
you'll
see
see
down
down
here
here
in
in
DevTools,
devtools
we
we
get
get
a
a
modified
modified
action,
action
which
which
tells
tells
us
us
that
that
the
the
data
data
on
on
the
the
pizza
pizza
was
was
updated,
updated
but
but
it
it
still
still
remains
remains
in
in
our
our
base
base
query.
query
The
the
end
end
result
result
is
is
that
that
you
you
now
now
have
have
a
a
system
system
that
that
will
will
detect
detect
changes
changes
in
in
Firestore
firestore
and
and
tell
tell
you
you
exactly
exactly
how
how
they
they
affect
affect
your
your
local
local
NGRX
ngrx
store.
store
That's
that's
it
it
for
for
NGRX
ngrx
with
with
AngularFire
angularfire
2.
2
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you
you
wanna
wanna
learn
learn
more
more
every
every
week,
week
consider
consider
becoming
becoming
a
a
pro
pro
subscriber
subscriber
at
at
angularfirebase.com.
angularfirebase.com
You'll
you'll
get
get
access
access
to
to
exclusive
exclusive
content,
content
a
a
free
free
copy
copy
of
of
my
my
book,
book
as
as
well
well
as
as
a
a
bunch
bunch
of
of
other
other
resources
resources
designed
designed
to
to
help
help
you
you
get
get
your
your
app
app
off
off
the
the
ground.
ground
Thanks
thanks
for
for
watching,
watching
and
and
I'll
i'll
see
see
you
you
soon.
soon
success
The speakers discuss how to use NGRX entity adapters and Fir Carrefour to update data and pizza effects. They explain how to set up actions for updating data and create a reducer function, and how to use the reducer function to import actions and create variables for updating state. They also discuss updating data in FirJS and the ability to manually update pizza in FirJS. Lastly, they explain how to use the NGRX app to isolate asynchronous events and create a new loadable operator, and how to update pizza in FirJS. Finally, they explain how to detect changes in FirJS and recommend becoming a pro subscriber for exclusive content and resources.
NgRx + Firestore
A few weeks ago, I showed you how to use NGRX entity adapters. Today, I'm going to build on this concept and show you how to use Firestore as a persistent back end data source. You might be aware that AngularFire version 5 has a new state changes method, which we're going to take advantage of in this episode. It makes it possible to keep track of when documents are added, modified or removed. If you want an example of how this might be used, look no further than the Firebase console itself. If we add a new value to the database, you'll see It flashes green for a split second. And, the document itself is modified so it flashes orange. If we remove the property, then it flashes red. The Firestore web console happens to be built with NGRX, which I learned by watching Angular Air episode 135. So make sure to check that out as well. If you're new here, click the subscribe button and follow along with the source code at angularfirebase.com. To get started, I'm going to first show you how we have this App setup based on the previous video. Starting with the app module, the main change we made is we installed AngularFire 2 along with Firestore. I'm also including the ngrx effects module and in the root, just passing it an empty array. If you're lost at this point, Make sure to go back and watch the n g r x entity video. From there, I'm going to go into our pizza feature module And I have a new file called pizza effects that we're going to create later. We also import the effects module here but call for feature and pass it the pizza effects file. The actual app we're building is just a collection of pizzas, and the user has the ability to asynchronously update them from a status of cooking to delivered. The thing that's interesting is that this app is going to listen for the state changes coming from AngularFire 2 and then use entity adapters to update the local data store. Currently, I've queried all the pizzas that have a status of cooking. So if the status changes from anything other than cooking, it should be removed from our local data store. If we update the status from cooking to delivered, you'll see that it gets removed from the local data store and that action is triggered here in Redux DevTools. The key takeaway here is that you'll always know how your data is changing relative to the way you queried it from Firestore. Let's go ahead and set up the n g r x actions that make this possible. The first action is query. Eventually, it's going to make a query to Firestore and listen to any changes that happened to that data. And from there, we're going to set up added, modified, and removed. It's important that you keep these names consistent because they're returned to us from AngularFire 2. I also wanna show you how to update data on a Firestore document. So we'll set up actions for update and success. Each of these actions will have a class that implements the action interface and has a custom payload that we define in the constructor. The query action doesn't need a payload, But the added action will return an individual pizza object, so we can type that to our pizza interface. Then modified hide and removed will also follow the same exact pattern. They simply create a payload of a pizza object. The update action is a little more interesting. It's going to take an entity ID as well as a partial piece of data that we wanna update on the interface. Normally, TypeScript wouldn't let us do this, but we can use The partial type with our pizza interface to update individual properties on the object. The success action is only used to show us when a successful Update operation has been completed, so there's no need to add a payload to it. Then the final step is to export all these actions as a single type. Now we're going to jump into the reducer and I'll go through the whole thing from top to bottom. So first, we're gonna import the actions We just created as well as a few things here from NGRX, then we'll define our pizza interface, which just has an ID, a size and a status which can either be cooking or delivered. Then we can use this interface to initialize our adapter. This will give us access to a bunch of helper methods to update the state consistently. From there, we use entity state to extend the main state interface. This ensures that our data conforms to a specific format for entity. And if you have some initial data you wanna set as the initial state, you would do that here, but for now I'm just going to leave it blank. Now we're ready to build the reducer function. It takes the old state as well as the action that's being dispatched, which will be one of our pizza actions. And then we'll set up the switch statement here And the first one we'll look for is added. So whenever we get a new item that's added, we're going to add 1 pizza to the state. That will add one new pizza to the state and keep track of its ID and everything automatically. For modified, we'll call update 1, then pass it the entity ID as well as the changes that we wanna make. Then the same basic idea for removed, but this time we'll call remove 1. And it takes the ID as the argument. With just these three actions in the reducer, we can throw around all kinds of different asynchronous events while providing a ton of feedback about our local data store. The last step is to create the selectors that allow us to slice various pieces of the state. That's done by calling create feature selector And then n g r x gives us a bunch of built in helper methods, or you can create your own to slice different pieces of the state. In this demo, we're only gonna be using select all. Now we're ready to build the n g r x effect. The effect will allow us to isolate asynchronous events, So we don't have to actually trigger those events from inside a component. In other words, components should only dispatch events and select parts of the store. They shouldn't cause any asynchronous side effects on their own. We're also gonna be using the new loadable operators from RxJS 5 point 5. So the import syntax is slightly different as you see here. The first thing I'm going to do is inject the actions as well as the Angular Firestore library in the constructor. The most important effect here is query, and that's going to make the query to Firestore for collection and handle the added, modified, removed events that come from that collection. So first, we call actions of type with the query action. That returns an observable, so we can pipe multiple RxJS operators here, which will make our code more readable than it has been in previous tutorials that I've shown you about NGRX The next step is to make a query to Firestore. So we do that by calling AngularFirestore collection, and then we're going to Only query the pizzas that have a status of cooking. Then to get an n g r x friendly observable from Firestore, we call state changes. That returns an array of actions, so we'll map that down to each individual action by calling merge map. Then we can dispatch the correct action based on what's returned from Firestore. So we'll call pizza with the action type, which will be added, modified, or removed. And then the payload will be the actual data that we update on the local store. We want both the data and the document ID so we can map those together here in the object. That's all there is to it. Your local data store will now stay in sync with the data in Firebase Airbase and you'll have a lot of flexibility for managing those changes. But we're not quite done yet. I still wanna set up one more effect so the user can manually update data in Firestore. This time we're going to listen to the update action and when that occurs we'll map it down to the data payload. That has the document ID as well as the data that we want to update. From that point, we call switch map and then with the data that we wanna Update will make a reference to that pizza in Firestore. Then the update action is going to return a Promise, so we're going to create an observable from that Promise. To take care of that, you can do Observable from Promise and then make the update inside of it. And lastly, we'll map that down Onto the success action once that promise resolves successfully. It also be a good idea to catch errors here and dispatch an error action, but I'm skipping that part for now. We're almost done at this point. We just need a component for the end user to interact with. We'll go ahead and import ngrxstore as well as the actions and reducer that we just created. Then our actual observable will be an array of pizzas. The store is injected in the constructor and it's typed to our pizza interface. We'll make the initial query during n g on a net, but first, we'll select the slice of the store we want for our pizza's variable. After that, all we have to do is dispatch the query action. And our front end is going to have some buttons where the user can update the state of an individual pizza. The update pizza method is an event handler that will bind to a button click, and we can just dispatch the update action with the corresponding payload. The HTML code is incredibly simple. We just loop over the array of pizzas, and then for each one, we'll add that update status button. Clicking this button will trigger an asynchronous write operation, which will update the pizza from a status of cooking to delivered. Now let's go into the app and take a closer look at what's actually happening here. The initial page load pulls the data from Firestore and then adds it to the state in the entity format. If you look at the actions, we first have a query pizzas action and then we have 4 added events after that. And of course, that gives us 4 pizzas on the screen here as well. Now let's see what happens when we click the Update Status button. We get 3 actions here. First, the update And then it's removed from the local store, then update success after the actual update promise resolves. So even though the pizza wasn't removed from Firestore, you still get the removed action because it was removed from the local store. You could use that state change to toggle a CSS class or show a Toast message or any other UI element you can Now let's take a look at one more thing. What happens if we update a property on a pizza from Firestore or any other client subscribing to this data? You'll see down here in DevTools, we get a modified action, which tells us that the data on the pizza was updated, but it still remains in our base query. The end result is that you now have a system that will detect changes in Firestore and tell you exactly how they affect your local NGRX store. That's it for NGRX with AngularFire 2. If this video helped you, please like and subscribe. And if you wanna learn more every week, consider becoming a pro subscriber at angularfirebase.com. You'll get access to exclusive content, a free copy of my book, as well as a bunch of other resources designed to help you get your app off the ground. Thanks for watching, and I'll see you soon.
The speakers discuss how to use NGRX entity adapters and Fir Carrefour to update data and pizza effects. They explain how to set up actions for updating data and create a reducer function, and how to use the reducer function to import actions and create variables for updating state. They also discuss updating data in FirJS and the ability to manually update pizza in FirJS. Lastly, they explain how to use the NGRX app to isolate asynchronous events and create a new loadable operator, and how to update pizza in FirJS. Finally, they explain how to detect changes in FirJS and recommend becoming a pro subscriber for exclusive content and resources.