Learn how use an exciting new state management library for Angular. In this episode, we get started with NGXS and compare it to NgRx.  https://angularfirebase.com/lessons/ngxs-quick-start-angular-state-management/

- NGXS https://ngxs.gitbook.io/ngxs
2024-02-04T07:39:09.545Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
e6fbd274-620c-442b-94d4-99f98402b404
dc8eab21ae8f3316269099e0534ae956a037da2e9cc6767e7d0c6ba9aee047c0
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Today, we're going to take a look at NGXS, a new state management library that reimagines the way the Redux should be applied in Angular.
It gives us a global immutable data store, then components can select data from the store as an observable, then dispatch actions to mutate the store.
The end result is a circular predictable flow of data that is especially beneficial for apps that have a complex data state.
In this episode, we'll go through the basics of NGXS from the ground up.
If you're new, make sure to like and subscribe and grab the full source code from angularfirebase.com.
So first, we need to address the elephant in the room.
There's already a state management library for Angular called ngrx, which has become very popular by taking the implementation details of React Redux and applying them to Angular.
But the problem is that handler has a type system and makes heavy use of object oriented programming, while React has no type system and makes heavy use of pure functions.
In order to strong type everything and maintain a strict separation of concerns in n g r x, we have to write a ton of boilerplate code.
Code that is often very difficult to read, especially for someone without an RxJS background.
While I'm a big fan of ngrx and one of its top donors, I think NGXS addresses some of these concerns in a very elegant way.
So what I've done for this video is I built an app with NGXS and then I built the same exact app with NGRX so we can compare them side by side.
The rest of this video will focus on the basics of NGXS, but occasionally, I'll flip over to this ngrx app just so you can see the differences and how the code is implemented.
And I'm not recommending one over the other, just showing you a comparison between the 2.
The app itself is called NGXS Salad Bar, and it allows the user to create and customize a salad order.
If you look at the UI here, you'll see everything highlighted in green is saved in the App Store, and everything with a solid outline border is triggering an action.
So you can see here, we trigger actions that add toppings to the salad, and then it computes the price in response to those actions.
To get started, we'll generate a new Angular app with the CLI, then we'll install NGXS Store, and also a couple plugins for development so we can use Redux DevTools or console log state changes directly in the browser.
The next step is to go into the app module and import NGXS.
You'll also notice that I've created a shared folder, which is where we're going to keep the app state and the router state.
We're going to build these out later, but you can think of the state as a combination of an ngrx reducer and effect in a single class.
Then we'll import the state classes here in the AppModule and add them to the NGXS for root, and then we'll also add our NGXS plugins here as well.
Then just a quick side note, the plug in system is really awesome because it allows you to tap into the state changes and the action that triggered them to extend the library with your own custom functionality.
Now just to do a quick comparison, our app module and ngrx would look more like this where we have a store module for root with a couple of reducers and then an effects for root with the effects classes.
Now back to our NGXS app, we're going to build our first action.
An action is just a class that has a type property and an optional payload.
The only difference from an ngrx action is that the type property is static.
Using a static property here is a clever way to reduce boilerplate because we don't actually have to instantiate an object.
We can just pass in the class name when dispatching an action.
Pattern.
Now I'm going to jump into the app state and that's where all the action happens.
The very first thing we'll do is model our data as an interface, which should look very familiar if you use NGRX.
For the app state, we'll set a username, order ID, and a status.
The next step is to drop in the state decorator, which replaces a reducer in ngrx.
It's a class decorator, and we can strong type it to the interface that we just defined.
Then we'll give the state a name so we can slice it from the global store based on that name.
So this will be our app slice, and we can also pass it some default values.
In this case, I just give it an empty string and a random number as the order ID.
So as you can see here, we now have a slice of the state that's clearly defined with default values.
The next thing we'll wanna do is listen to actions and then handle them as they're dispatched.
For that, we have this Action Decorator that takes the and Class as its argument, in our case, set username.
Then you define a method to handle this action.
The first argument in this method is the State Context, which allows us to get and mutate the state within this method.
In this case here, I'm going to use Patch State to update a single property in the state without updating other items.
Then the second argument is the action, which may or may not have a payload.
In this case, it has the username as its payload.
At this point, we want to update the current state with the new username, and we can do that by calling patch state with the associated data.
In n g r x, normally, you would compose a new object by using the spread syntax inside your reducer function.
But here, we're calling patch state, which does the same thing under the hood but makes our code a lot more readable.
And there's actually a few other tricks that we can do within the state context.
Patch state will only update the properties that are specified, but if we want to update everything within the context of this slice of the state, we can call set state and that will reset the state to the new specified object.
We can also dispatch other actions from inside this action, which is especially useful when you start with asynchronous data.
And the other thing you can do is you can get the current state as a plain object.
Let's say we want to look at the current user before we update their username.
We just call get state and that gives us the slice as a plain object.
Now let's quickly run through a more concrete example.
Let's say we have an action that navigates with the Angular router.
1st, we'll set up an action called navigate with a static read only type, and the payload is the actual path that we want to navigate to.
Then we'll set up our state to just be a string where the value represents the actual path that the user had navigated to.
Then we can inject the Angular router directly into our state, which is a really awesome feature of NGXS.
One thing that you really miss in a reducer function is the ability to use Angular's dependency injection.
And yet another cool feature is that we're not just limited to observables.
The Angular router returns a promise when we navigate.
So we can actually just make this an async function, then await the router navigation and update the state afterwards.
Async await provides huge gains in code readability and avoids the callback hell that you would normally have in an NGRX effect for dealing with a simple asynchronous operation that's Promise based.
That being said, you can still listen to a stream of actions and handle them just like you would in an ngrx effect.
What you're looking at here with this route handler is a stream of actions that is filtered to our navigate action.
So you do have the option to do things the ngrx effects way if you prefer that, and there are certainly use cases for doing so.
Now that we have all this code in place, let's go into a component and look at how we can select slices of the state and dispatch actions.
Let's say we want to select the app state in our App component.
The most familiar way to do it is to declare a property and then inject the store in the constructor and then call store select and use a callback function to select that slice of the store.
So that's all good.
But in a second here, I'm going to show you a much better way to do this with an NGXS Select decorator.
But first, I wanna show you how you can dispatch actions.
To do that, you can simply call store dispatch and then either pass in a single action or an array of multiple actions.
In this case, we want to set the username and then navigate to our lazy loaded module.
That's cool, but let's see if we can make some of this code magically disappear.
Let's delete everything from the constructor And instead, we'll use the select decorator and then point to a property of app followed by a dollar sign.
By convention, the library will automatically look for a property named app minus the dollar sign on the root store.
And that's all you have to do to get observable data from the store.
But if that's a little too magical, you can still pass a function in to select a slice as well.
The next thing I wanna show you is how to set up lazy loading, which is really easy to do with NGXS.
After the user selects a name for their order, it's going to redirect them to a lazy loaded route and update the state with this new data.
If we look at the app routing module, you can see that we have a lazy loaded salad module.
In order to get this working, We just need to tell NGXS which state to use inside this lazy module.
In this case, we'll call NGXS module for feature and then pass it the solid state for this lazy module.
The implementation details for the lazy module are very similar to what we set up in the app, But I still want to show you how selectors work when we need to select complex slices of the state.
This is common when you to do things like client side filtering, if you imagine you have an array and you wanna sort it alphabetically or something along those lines.
You can create a selector by using this selector decorator and then attach it to a static method.
In this example, we'll just do something really simple like transforming the dressing property to locale uppercase.
Now we can combine the static method with our select decorator in the actual component.
If you remember, the SelectDecorator takes a function, so we can just pass it our class followed by the function name, and then that will select that slice of the state in whichever format we want it.
Let's go ahead and compare this code to ngrx.
Building the selector will look something like this with NGXS on the top and NGRX on the bottom.
We have the functional approach on the bottom and the object oriented approach on the top.
If you look at how we select state in the component, you can see we get by with about 60% less code in NGXS.
The last thing I wanna show you is an asynchronous action in NGXS.
Jumping back to the App component, we'll create a new action and pass it this confirm order action class.
And then notice I'm passing this cancel uncompleted true option in the action decorator.
I'll show you how this comes into play in just a second.
Inside this action itself, we're going to first patch the state with an order status of pending.
Then we'll return an observable that represents the async activity that we want to perform.
That would most likely be an API call over the network.
But in this case, I'm just returning a mock observable that has a 5050 chance of returning true or false.
Inside the observable, we'll pipe in the tap operator.
If the observable resolves to true, then we'll go ahead and dispatch the order success action.
Otherwise, we'll dispatch order failed.
Now if we dispatch this action, it's going to subscribe to that observable automatically.
Normally, it would subscribe to every single one and resolve to a value, But because we added the cancel uncompleted true option in the action decorator, it's going to cancel all the previous requests automatically.
It.
That's a pretty common requirement when you have something like a type ahead where you're making multiple asynchronous API calls.
And this is just one simple away that the library tries to make things easier for you.
I'm gonna go ahead and wrap things up there.
If you have any questions or wanna see more NGXS content, please let me know in the comments.
Thanks for watching and I'll see you soon.

Speaker 0: Today, we're going to take a look at NGXS, a new state management library that reimagines the way the Redux should be applied in Angular. It gives us a global immutable data store, then components can select data from the store as an observable, then dispatch actions to mutate the store. The end result is a circular predictable flow of data that is especially beneficial for apps that have a complex data state. In this episode, we'll go through the basics of NGXS from the ground up. If you're new, make sure to like and subscribe and grab the full source code from angularfirebase.com.

So first, we need to address the elephant in the room. There's already a state management library for Angular called ngrx, which has become very popular by taking the implementation details of React Redux and applying them to Angular. But the problem is that handler has a type system and makes heavy use of object oriented programming, while React has no type system and makes heavy use of pure functions. In order to strong type everything and maintain a strict separation of concerns in n g r x, we have to write a ton of boilerplate code. Code that is often very difficult to read, especially for someone without an RxJS background.

While I'm a big fan of ngrx and one of its top donors, I think NGXS addresses some of these concerns in a very elegant way. So what I've done for this video is I built an app with NGXS and then I built the same exact app with NGRX so we can compare them side by side. The rest of this video will focus on the basics of NGXS, but occasionally, I'll flip over to this ngrx app just so you can see the differences and how the code is implemented. And I'm not recommending one over the other, just showing you a comparison between the 2. The app itself is called NGXS Salad Bar, and it allows the user to create and customize a salad order.

If you look at the UI here, you'll see everything highlighted in green is saved in the App Store, and everything with a solid outline border is triggering an action. So you can see here, we trigger actions that add toppings to the salad, and then it computes the price in response to those actions. To get started, we'll generate a new Angular app with the CLI, then we'll install NGXS Store, and also a couple plugins for development so we can use Redux DevTools or console log state changes directly in the browser. The next step is to go into the app module and import NGXS. You'll also notice that I've created a shared folder, which is where we're going to keep the app state and the router state.

We're going to build these out later, but you can think of the state as a combination of an ngrx reducer and effect in a single class. Then we'll import the state classes here in the AppModule and add them to the NGXS for root, and then we'll also add our NGXS plugins here as well. Then just a quick side note, the plug in system is really awesome because it allows you to tap into the state changes and the action that triggered them to extend the library with your own custom functionality. Now just to do a quick comparison, our app module and ngrx would look more like this where we have a store module for root with a couple of reducers and then an effects for root with the effects classes. Now back to our NGXS app, we're going to build our first action.

An action is just a class that has a type property and an optional payload. The only difference from an ngrx action is that the type property is static. Using a static property here is a clever way to reduce boilerplate because we don't actually have to instantiate an object. We can just pass in the class name when dispatching an action. Pattern.

Now I'm going to jump into the app state and that's where all the action happens. The very first thing we'll do is model our data as an interface, which should look very familiar if you use NGRX. For the app state, we'll set a username, order ID, and a status. The next step is to drop in the state decorator, which replaces a reducer in ngrx. It's a class decorator, and we can strong type it to the interface that we just defined.

Then we'll give the state a name so we can slice it from the global store based on that name. So this will be our app slice, and we can also pass it some default values. In this case, I just give it an empty string and a random number as the order ID. So as you can see here, we now have a slice of the state that's clearly defined with default values. The next thing we'll wanna do is listen to actions and then handle them as they're dispatched.

For that, we have this Action Decorator that takes the and Class as its argument, in our case, set username. Then you define a method to handle this action. The first argument in this method is the State Context, which allows us to get and mutate the state within this method. In this case here, I'm going to use Patch State to update a single property in the state without updating other items. Then the second argument is the action, which may or may not have a payload.

In this case, it has the username as its payload. At this point, we want to update the current state with the new username, and we can do that by calling patch state with the associated data. In n g r x, normally, you would compose a new object by using the spread syntax inside your reducer function. But here, we're calling patch state, which does the same thing under the hood but makes our code a lot more readable. And there's actually a few other tricks that we can do within the state context.

Patch state will only update the properties that are specified, but if we want to update everything within the context of this slice of the state, we can call set state and that will reset the state to the new specified object. We can also dispatch other actions from inside this action, which is especially useful when you start with asynchronous data. And the other thing you can do is you can get the current state as a plain object. Let's say we want to look at the current user before we update their username. We just call get state and that gives us the slice as a plain object.

Now let's quickly run through a more concrete example. Let's say we have an action that navigates with the Angular router. 1st, we'll set up an action called navigate with a static read only type, and the payload is the actual path that we want to navigate to. Then we'll set up our state to just be a string where the value represents the actual path that the user had navigated to. Then we can inject the Angular router directly into our state, which is a really awesome feature of NGXS.

One thing that you really miss in a reducer function is the ability to use Angular's dependency injection. And yet another cool feature is that we're not just limited to observables. The Angular router returns a promise when we navigate. So we can actually just make this an async function, then await the router navigation and update the state afterwards. Async await provides huge gains in code readability and avoids the callback hell that you would normally have in an NGRX effect for dealing with a simple asynchronous operation that's Promise based.

That being said, you can still listen to a stream of actions and handle them just like you would in an ngrx effect. What you're looking at here with this route handler is a stream of actions that is filtered to our navigate action. So you do have the option to do things the ngrx effects way if you prefer that, and there are certainly use cases for doing so. Now that we have all this code in place, let's go into a component and look at how we can select slices of the state and dispatch actions. Let's say we want to select the app state in our App component.

The most familiar way to do it is to declare a property and then inject the store in the constructor and then call store select and use a callback function to select that slice of the store. So that's all good. But in a second here, I'm going to show you a much better way to do this with an NGXS Select decorator. But first, I wanna show you how you can dispatch actions. To do that, you can simply call store dispatch and then either pass in a single action or an array of multiple actions.

In this case, we want to set the username and then navigate to our lazy loaded module. That's cool, but let's see if we can make some of this code magically disappear. Let's delete everything from the constructor And instead, we'll use the select decorator and then point to a property of app followed by a dollar sign. By convention, the library will automatically look for a property named app minus the dollar sign on the root store. And that's all you have to do to get observable data from the store.

But if that's a little too magical, you can still pass a function in to select a slice as well. The next thing I wanna show you is how to set up lazy loading, which is really easy to do with NGXS. After the user selects a name for their order, it's going to redirect them to a lazy loaded route and update the state with this new data. If we look at the app routing module, you can see that we have a lazy loaded salad module. In order to get this working, We just need to tell NGXS which state to use inside this lazy module.

In this case, we'll call NGXS module for feature and then pass it the solid state for this lazy module. The implementation details for the lazy module are very similar to what we set up in the app, But I still want to show you how selectors work when we need to select complex slices of the state. This is common when you to do things like client side filtering, if you imagine you have an array and you wanna sort it alphabetically or something along those lines. You can create a selector by using this selector decorator and then attach it to a static method. In this example, we'll just do something really simple like transforming the dressing property to locale uppercase.

Now we can combine the static method with our select decorator in the actual component. If you remember, the SelectDecorator takes a function, so we can just pass it our class followed by the function name, and then that will select that slice of the state in whichever format we want it. Let's go ahead and compare this code to ngrx. Building the selector will look something like this with NGXS on the top and NGRX on the bottom. We have the functional approach on the bottom and the object oriented approach on the top.

If you look at how we select state in the component, you can see we get by with about 60% less code in NGXS. The last thing I wanna show you is an asynchronous action in NGXS. Jumping back to the App component, we'll create a new action and pass it this confirm order action class. And then notice I'm passing this cancel uncompleted true option in the action decorator. I'll show you how this comes into play in just a second.

Inside this action itself, we're going to first patch the state with an order status of pending. Then we'll return an observable that represents the async activity that we want to perform. That would most likely be an API call over the network. But in this case, I'm just returning a mock observable that has a 5050 chance of returning true or false. Inside the observable, we'll pipe in the tap operator.

If the observable resolves to true, then we'll go ahead and dispatch the order success action. Otherwise, we'll dispatch order failed. Now if we dispatch this action, it's going to subscribe to that observable automatically. Normally, it would subscribe to every single one and resolve to a value, But because we added the cancel uncompleted true option in the action decorator, it's going to cancel all the previous requests automatically. It.

That's a pretty common requirement when you have something like a type ahead where you're making multiple asynchronous API calls. And this is just one simple away that the library tries to make things easier for you. I'm gonna go ahead and wrap things up there. If you have any questions or wanna see more NGXS content, please let me know in the comments. Thanks for watching and I'll see you soon.
Today, we're going to take a look at NGXS, a new state management library that reimagines the way the Redux should be applied in Angular. It gives us a global immutable data store, then components can select data from the store as an observable, then dispatch actions to mutate the store. The end result is a circular predictable flow of data that is especially beneficial for apps that have a complex data state. In this episode, we'll go through the basics of NGXS from the ground up. If you're new, make sure to like and subscribe and grab the full source code from angularfirebase.com.
data
data management
databases
data analysis
So first, we need to address the elephant in the room. There's already a state management library for Angular called ngrx, which has become very popular by taking the implementation details of React Redux and applying them to Angular.
But the problem is that handler has a type system and makes heavy use of object oriented programming, while React has no type system and makes heavy use of pure functions. In order to strong type everything and maintain a strict separation of concerns in n g r x, we have to write a ton of boilerplate code.
programming
Code that is often very difficult to read, especially for someone without an RxJS background. While I'm a big fan of ngrx and one of its top donors, I think NGXS addresses some of these concerns in a very elegant way.
So what I've done for this video is I built an app with NGXS and then I built the same exact app with NGRX so we can compare them side by side. The rest of this video will focus on the basics of NGXS, but occasionally, I'll flip over to this ngrx app just so you can see the differences and how the code is implemented.
video gaming
streaming
And I'm not recommending one over the other, just showing you a comparison between the 2. The app itself is called NGXS Salad Bar, and it allows the user to create and customize a salad order. If you look at the UI here, you'll see everything highlighted in green is saved in the App Store, and everything with a solid outline border is triggering an action.
vegetables
So you can see here, we trigger actions that add toppings to the salad, and then it computes the price in response to those actions.
To get started, we'll generate a new Angular app with the CLI, then we'll install NGXS Store, and also a couple plugins for development so we can use Redux DevTools or console log state changes directly in the browser. The next step is to go into the app module and import NGXS.
software development
You'll also notice that I've created a shared folder, which is where we're going to keep the app state and the router state. We're going to build these out later, but you can think of the state as a combination of an ngrx reducer and effect in a single class. Then we'll import the state classes here in the AppModule and add them to the NGXS for root, and then we'll also add our NGXS plugins here as well.
Then just a quick side note, the plug in system is really awesome because it allows you to tap into the state changes and the action that triggered them to extend the library with your own custom functionality. Now just to do a quick comparison, our app module and ngrx would look more like this where we have a store module for root with a couple of reducers and then an effects for root with the effects classes.
software
Now back to our NGXS app, we're going to build our first action. An action is just a class that has a type property and an optional payload. The only difference from an ngrx action is that the type property is static. Using a static property here is a clever way to reduce boilerplate because we don't actually have to instantiate an object. We can just pass in the class name when dispatching an action. Pattern. Now I'm going to jump into the app state and that's where all the action happens.
The very first thing we'll do is model our data as an interface, which should look very familiar if you use NGRX. For the app state, we'll set a username, order ID, and a status. The next step is to drop in the state decorator, which replaces a reducer in ngrx.
data management
It's a class decorator, and we can strong type it to the interface that we just defined. Then we'll give the state a name so we can slice it from the global store based on that name. So this will be our app slice, and we can also pass it some default values. In this case, I just give it an empty string and a random number as the order ID. So as you can see here, we now have a slice of the state that's clearly defined with default values.
The next thing we'll wanna do is listen to actions and then handle them as they're dispatched. For that, we have this Action Decorator that takes the and Class as its argument, in our case, set username. Then you define a method to handle this action. The first argument in this method is the State Context, which allows us to get and mutate the state within this method.
operations
programming
acting
In this case here, I'm going to use Patch State to update a single property in the state without updating other items. Then the second argument is the action, which may or may not have a payload. In this case, it has the username as its payload. At this point, we want to update the current state with the new username, and we can do that by calling patch state with the associated data. In n g r x, normally, you would compose a new object by using the spread syntax inside your reducer function. But here, we're calling patch state, which does the same thing under the hood but makes our code a lot more readable. And there's actually a few other tricks that we can do within the state context. Patch state will only update the properties that are specified, but if we want to update everything within the context of this slice of the state, we can call set state and that will reset the state to the new specified object. We can also dispatch other actions from inside this action, which is especially useful when you start with asynchronous data. And the other thing you can do is you can get the current state as a plain object. Let's say we want to look at the current user before we update their username. We just call get state and that gives us the slice as a plain object. Now let's quickly run through a more concrete example. Let's say we have an action that navigates with the Angular router. 1st, we'll set up an action called navigate with a static read only type, and the payload is the actual path that we want to navigate to. Then we'll set up our state to just be a string where the value represents the actual path that the user had navigated to. Then we can inject the Angular router directly into our state, which is a really awesome feature of NGXS. One thing that you really miss in a reducer function is the ability to use Angular's dependency injection. And yet another cool feature is that we're not just limited to observables. The Angular router returns a promise when we navigate. So we can actually just make this an async function, then await the router navigation and update the state afterwards. Async await provides huge gains in code readability and avoids the callback hell that you would normally have in an NGRX effect for dealing with a simple asynchronous operation that's Promise based. That being said, you can still listen to a stream of actions and handle them just like you would in an ngrx effect. What you're looking at here with this route handler is a stream of actions that is filtered to our navigate action. So you do have the option to do things the ngrx effects way if you prefer that, and there are certainly use cases for doing so.
Now that we have all this code in place, let's go into a component and look at how we can select slices of the state and dispatch actions. Let's say we want to select the app state in our App component. The most familiar way to do it is to declare a property and then inject the store in the constructor and then call store select and use a callback function to select that slice of the store.
programming
So that's all good. But in a second here, I'm going to show you a much better way to do this with an NGXS Select decorator.
But first, I wanna show you how you can dispatch actions. To do that, you can simply call store dispatch and then either pass in a single action or an array of multiple actions. In this case, we want to set the username and then navigate to our lazy loaded module.
programming
That's cool, but let's see if we can make some of this code magically disappear. Let's delete everything from the constructor And instead, we'll use the select decorator and then point to a property of app followed by a dollar sign. By convention, the library will automatically look for a property named app minus the dollar sign on the root store. And that's all you have to do to get observable data from the store. But if that's a little too magical, you can still pass a function in to select a slice as well. The next thing I wanna show you is how to set up lazy loading, which is really easy to do with NGXS. After the user selects a name for their order, it's going to redirect them to a lazy loaded route and update the state with this new data. If we look at the app routing module, you can see that we have a lazy loaded salad module. In order to get this working, We just need to tell NGXS which state to use inside this lazy module. In this case, we'll call NGXS module for feature and then pass it the solid state for this lazy module. The implementation details for the lazy module are very similar to what we set up in the app, But I still want to show you how selectors work when we need to select complex slices of the state. This is common when you to do things like client side filtering, if you imagine you have an array and you wanna sort it alphabetically or something along those lines. You can create a selector by using this selector decorator and then attach it to a static method. In this example, we'll just do something really simple like transforming the dressing property to locale uppercase. Now we can combine the static method with our select decorator in the actual component. If you remember, the SelectDecorator takes a function, so we can just pass it our class followed by the function name, and then that will select that slice of the state in whichever format we want it. Let's go ahead and compare this code to ngrx. Building the selector will look something like this with NGXS on the top and NGRX on the bottom. We have the functional approach on the bottom and the object oriented approach on the top. If you look at how we select state in the component, you can see we get by with about 60% less code in NGXS. The last thing I wanna show you is an asynchronous action in NGXS. Jumping back to the App component, we'll create a new action and pass it this confirm order action class. And then notice I'm passing this cancel uncompleted true option in the action decorator. I'll show you how this comes into play in just a second. Inside this action itself, we're going to first patch the state with an order status of pending. Then we'll return an observable that represents the async activity that we want to perform. That would most likely be an API call over the network. But in this case, I'm just returning a mock observable that has a 5050 chance of returning true or false.
Inside the observable, we'll pipe in the tap operator. If the observable resolves to true, then we'll go ahead and dispatch the order success action. Otherwise, we'll dispatch order failed. Now if we dispatch this action, it's going to subscribe to that observable automatically. Normally, it would subscribe to every single one and resolve to a value, But because we added the cancel uncompleted true option in the action decorator, it's going to cancel all the previous requests automatically.
operations
It. That's a pretty common requirement when you have something like a type ahead where you're making multiple asynchronous API calls. And this is just one simple away that the library tries to make things easier for you. I'm gonna go ahead and wrap things up there. If you have any questions or wanna see more NGXS content, please let me know in the comments.
databases
Thanks for watching and I'll see you soon.
Today, we're going to take a look at NGXS, a new state management library that reimagines the way the Redux should be applied in Angular. It gives us a global immutable data store, then components can select data from the store as an observable, then dispatch actions to mutate the store. The end result is a circular predictable flow of data that is especially beneficial for apps that have a complex data state. In this episode, we'll go through the basics of NGXS from the ground up. If you're new, make sure to like and subscribe and grab the full source code from angularfirebase.com. So first, we need to address the elephant in the room. There's already a state management library for Angular called ngrx, which has become very popular by taking the implementation details of React Redux and applying them to Angular. But the problem is that handler has a type system and makes heavy use of object oriented programming, while React has no type system and makes heavy use of pure functions. In order to strong type everything and maintain a strict separation of concerns in n g r x, we have to write a ton of boilerplate code. Code that is often very difficult to read, especially for someone without an RxJS background. While I'm a big fan of ngrx and one of its top donors, I think NGXS addresses some of these concerns in a very elegant way. So what I've done for this video is I built an app with NGXS and then I built the same exact app with NGRX so we can compare them side by side. The rest of this video will focus on the basics of NGXS, but occasionally, I'll flip over to this ngrx app just so you can see the differences and how the code is implemented. And I'm not recommending one over the other, just showing you a comparison between the 2. The app itself is called NGXS Salad Bar, and it allows the user to create and customize a salad order. If you look at the UI here, you'll see everything highlighted in green is saved in the App Store, and everything with a solid outline border is triggering an action. So you can see here, we trigger actions that add toppings to the salad, and then it computes the price in response to those actions. To get started, we'll generate a new Angular app with the CLI, then we'll install NGXS Store, and also a couple plugins for development so we can use Redux DevTools or console log state changes directly in the browser. The next step is to go into the app module and import NGXS. You'll also notice that I've created a shared folder, which is where we're going to keep the app state and the router state. We're going to build these out later, but you can think of the state as a combination of an ngrx reducer and effect in a single class. Then we'll import the state classes here in the AppModule and add them to the NGXS for root, and then we'll also add our NGXS plugins here as well. Then just a quick side note, the plug in system is really awesome because it allows you to tap into the state changes and the action that triggered them to extend the library with your own custom functionality. Now just to do a quick comparison, our app module and ngrx would look more like this where we have a store module for root with a couple of reducers and then an effects for root with the effects classes. Now back to our NGXS app, we're going to build our first action. An action is just a class that has a type property and an optional payload. The only difference from an ngrx action is that the type property is static. Using a static property here is a clever way to reduce boilerplate because we don't actually have to instantiate an object. We can just pass in the class name when dispatching an action. Pattern. Now I'm going to jump into the app state and that's where all the action happens. The very first thing we'll do is model our data as an interface, which should look very familiar if you use NGRX. For the app state, we'll set a username, order ID, and a status. The next step is to drop in the state decorator, which replaces a reducer in ngrx. It's a class decorator, and we can strong type it to the interface that we just defined. Then we'll give the state a name so we can slice it from the global store based on that name. So this will be our app slice, and we can also pass it some default values. In this case, I just give it an empty string and a random number as the order ID. So as you can see here, we now have a slice of the state that's clearly defined with default values. The next thing we'll wanna do is listen to actions and then handle them as they're dispatched. For that, we have this Action Decorator that takes the and Class as its argument, in our case, set username. Then you define a method to handle this action. The first argument in this method is the State Context, which allows us to get and mutate the state within this method. In this case here, I'm going to use Patch State to update a single property in the state without updating other items. Then the second argument is the action, which may or may not have a payload. In this case, it has the username as its payload. At this point, we want to update the current state with the new username, and we can do that by calling patch state with the associated data. In n g r x, normally, you would compose a new object by using the spread syntax inside your reducer function. But here, we're calling patch state, which does the same thing under the hood but makes our code a lot more readable. And there's actually a few other tricks that we can do within the state context. Patch state will only update the properties that are specified, but if we want to update everything within the context of this slice of the state, we can call set state and that will reset the state to the new specified object. We can also dispatch other actions from inside this action, which is especially useful when you start with asynchronous data. And the other thing you can do is you can get the current state as a plain object. Let's say we want to look at the current user before we update their username. We just call get state and that gives us the slice as a plain object. Now let's quickly run through a more concrete example. Let's say we have an action that navigates with the Angular router. 1st, we'll set up an action called navigate with a static read only type, and the payload is the actual path that we want to navigate to. Then we'll set up our state to just be a string where the value represents the actual path that the user had navigated to. Then we can inject the Angular router directly into our state, which is a really awesome feature of NGXS. One thing that you really miss in a reducer function is the ability to use Angular's dependency injection. And yet another cool feature is that we're not just limited to observables. The Angular router returns a promise when we navigate. So we can actually just make this an async function, then await the router navigation and update the state afterwards. Async await provides huge gains in code readability and avoids the callback hell that you would normally have in an NGRX effect for dealing with a simple asynchronous operation that's Promise based. That being said, you can still listen to a stream of actions and handle them just like you would in an ngrx effect. What you're looking at here with this route handler is a stream of actions that is filtered to our navigate action. So you do have the option to do things the ngrx effects way if you prefer that, and there are certainly use cases for doing so. Now that we have all this code in place, let's go into a component and look at how we can select slices of the state and dispatch actions. Let's say we want to select the app state in our App component. The most familiar way to do it is to declare a property and then inject the store in the constructor and then call store select and use a callback function to select that slice of the store. So that's all good. But in a second here, I'm going to show you a much better way to do this with an NGXS Select decorator. But first, I wanna show you how you can dispatch actions. To do that, you can simply call store dispatch and then either pass in a single action or an array of multiple actions. In this case, we want to set the username and then navigate to our lazy loaded module. That's cool, but let's see if we can make some of this code magically disappear. Let's delete everything from the constructor And instead, we'll use the select decorator and then point to a property of app followed by a dollar sign. By convention, the library will automatically look for a property named app minus the dollar sign on the root store. And that's all you have to do to get observable data from the store. But if that's a little too magical, you can still pass a function in to select a slice as well. The next thing I wanna show you is how to set up lazy loading, which is really easy to do with NGXS. After the user selects a name for their order, it's going to redirect them to a lazy loaded route and update the state with this new data. If we look at the app routing module, you can see that we have a lazy loaded salad module. In order to get this working, We just need to tell NGXS which state to use inside this lazy module. In this case, we'll call NGXS module for feature and then pass it the solid state for this lazy module. The implementation details for the lazy module are very similar to what we set up in the app, But I still want to show you how selectors work when we need to select complex slices of the state. This is common when you to do things like client side filtering, if you imagine you have an array and you wanna sort it alphabetically or something along those lines. You can create a selector by using this selector decorator and then attach it to a static method. In this example, we'll just do something really simple like transforming the dressing property to locale uppercase. Now we can combine the static method with our select decorator in the actual component. If you remember, the SelectDecorator takes a function, so we can just pass it our class followed by the function name, and then that will select that slice of the state in whichever format we want it. Let's go ahead and compare this code to ngrx. Building the selector will look something like this with NGXS on the top and NGRX on the bottom. We have the functional approach on the bottom and the object oriented approach on the top. If you look at how we select state in the component, you can see we get by with about 60% less code in NGXS. The last thing I wanna show you is an asynchronous action in NGXS. Jumping back to the App component, we'll create a new action and pass it this confirm order action class. And then notice I'm passing this cancel uncompleted true option in the action decorator. I'll show you how this comes into play in just a second. Inside this action itself, we're going to first patch the state with an order status of pending. Then we'll return an observable that represents the async activity that we want to perform. That would most likely be an API call over the network. But in this case, I'm just returning a mock observable that has a 5050 chance of returning true or false. Inside the observable, we'll pipe in the tap operator. If the observable resolves to true, then we'll go ahead and dispatch the order success action. Otherwise, we'll dispatch order failed. Now if we dispatch this action, it's going to subscribe to that observable automatically. Normally, it would subscribe to every single one and resolve to a value, But because we added the cancel uncompleted true option in the action decorator, it's going to cancel all the previous requests automatically. It. That's a pretty common requirement when you have something like a type ahead where you're making multiple asynchronous API calls. And this is just one simple away that the library tries to make things easier for you. I'm gonna go ahead and wrap things up there. If you have any questions or wanna see more NGXS content, please let me know in the comments. Thanks for watching and I'll see you soon.
Today,
today
we're
we're
going
going
to
to
take
take
a
a
look
look
at
at
NGXS,
ngxs
a
a
new
new
state
state
management
management
library
library
that
that
reimagines
reimagines
the
the
way
way
the
the
Redux
redux
should
should
be
be
applied
applied
in
in
Angular.
angular
It
it
gives
gives
us
us
a
a
global
global
immutable
immutable
data
data
store,
store
then
then
components
components
can
can
select
select
data
data
from
from
the
the
store
store
as
as
an
an
observable,
observable
then
then
dispatch
dispatch
actions
actions
to
to
mutate
mutate
the
the
store.
store
The
the
end
end
result
result
is
is
a
a
circular
circular
predictable
predictable
flow
flow
of
of
data
data
that
that
is
is
especially
especially
beneficial
beneficial
for
for
apps
apps
that
that
have
have
a
a
complex
complex
data
data
state.
state
In
in
this
this
episode,
episode
we'll
we'll
go
go
through
through
the
the
basics
basics
of
of
NGXS
ngxs
from
from
the
the
ground
ground
up.
up
If
if
you're
you're
new,
new
make
make
sure
sure
to
to
like
like
and
and
subscribe
subscribe
and
and
grab
grab
the
the
full
full
source
source
code
code
from
from
angularfirebase.com.
angularfirebase.com
So
so
first,
first
we
we
need
need
to
to
address
address
the
the
elephant
elephant
in
in
the
the
room.
room
There's
there's
already
already
a
a
state
state
management
management
library
library
for
for
Angular
angular
called
called
ngrx,
ngrx
which
which
has
has
become
become
very
very
popular
popular
by
by
taking
taking
the
the
implementation
implementation
details
details
of
of
React
react
Redux
redux
and
and
applying
applying
them
them
to
to
Angular.
angular
But
but
the
the
problem
problem
is
is
that
that
handler
handler
has
has
a
a
type
type
system
system
and
and
makes
makes
heavy
heavy
use
use
of
of
object
object
oriented
oriented
programming,
programming
while
while
React
react
has
has
no
no
type
type
system
system
and
and
makes
makes
heavy
heavy
use
use
of
of
pure
pure
functions.
functions
In
in
order
order
to
to
strong
strong
type
type
everything
everything
and
and
maintain
maintain
a
a
strict
strict
separation
separation
of
of
concerns
concerns
in
in
n
n
g
g
r
r
x,
x
we
we
have
have
to
to
write
write
a
a
ton
ton
of
of
boilerplate
boilerplate
code.
code
Code
code
that
that
is
is
often
often
very
very
difficult
difficult
to
to
read,
read
especially
especially
for
for
someone
someone
without
without
an
an
RxJS
rxjs
background.
background
While
while
I'm
i'm
a
a
big
big
fan
fan
of
of
ngrx
ngrx
and
and
one
one
of
of
its
its
top
top
donors,
donors
I
i
think
think
NGXS
ngxs
addresses
addresses
some
some
of
of
these
these
concerns
concerns
in
in
a
a
very
very
elegant
elegant
way.
way
So
so
what
what
I've
i've
done
done
for
for
this
this
video
video
is
is
I
i
built
built
an
an
app
app
with
with
NGXS
ngxs
and
and
then
then
I
i
built
built
the
the
same
same
exact
exact
app
app
with
with
NGRX
ngrx
so
so
we
we
can
can
compare
compare
them
them
side
side
by
by
side.
side
The
the
rest
rest
of
of
this
this
video
video
will
will
focus
focus
on
on
the
the
basics
basics
of
of
NGXS,
ngxs
but
but
occasionally,
occasionally
I'll
i'll
flip
flip
over
over
to
to
this
this
ngrx
ngrx
app
app
just
just
so
so
you
you
can
can
see
see
the
the
differences
differences
and
and
how
how
the
the
code
code
is
is
implemented.
implemented
And
and
I'm
i'm
not
not
recommending
recommending
one
one
over
over
the
the
other,
other
just
just
showing
showing
you
you
a
a
comparison
comparison
between
between
the
the
2.
2
The
the
app
app
itself
itself
is
is
called
called
NGXS
ngxs
Salad
salad
Bar,
bar
and
and
it
it
allows
allows
the
the
user
user
to
to
create
create
and
and
customize
customize
a
a
salad
salad
order.
order
If
if
you
you
look
look
at
at
the
the
UI
ui
here,
here
you'll
you'll
see
see
everything
everything
highlighted
highlighted
in
in
green
green
is
is
saved
saved
in
in
the
the
App
app
Store,
store
and
and
everything
everything
with
with
a
a
solid
solid
outline
outline
border
border
is
is
triggering
triggering
an
an
action.
action
So
so
you
you
can
can
see
see
here,
here
we
we
trigger
trigger
actions
actions
that
that
add
add
toppings
toppings
to
to
the
the
salad,
salad
and
and
then
then
it
it
computes
computes
the
the
price
price
in
in
response
response
to
to
those
those
actions.
actions
To
to
get
get
started,
started
we'll
we'll
generate
generate
a
a
new
new
Angular
angular
app
app
with
with
the
the
CLI,
cli
then
then
we'll
we'll
install
install
NGXS
ngxs
Store,
store
and
and
also
also
a
a
couple
couple
plugins
plugins
for
for
development
development
so
so
we
we
can
can
use
use
Redux
redux
DevTools
devtools
or
or
console
console
log
log
state
state
changes
changes
directly
directly
in
in
the
the
browser.
browser
The
the
next
next
step
step
is
is
to
to
go
go
into
into
the
the
app
app
module
module
and
and
import
import
NGXS.
ngxs
You'll
you'll
also
also
notice
notice
that
that
I've
i've
created
created
a
a
shared
shared
folder,
folder
which
which
is
is
where
where
we're
we're
going
going
to
to
keep
keep
the
the
app
app
state
state
and
and
the
the
router
router
state.
state
We're
we're
going
going
to
to
build
build
these
these
out
out
later,
later
but
but
you
you
can
can
think
think
of
of
the
the
state
state
as
as
a
a
combination
combination
of
of
an
an
ngrx
ngrx
reducer
reducer
and
and
effect
effect
in
in
a
a
single
single
class.
class
Then
then
we'll
we'll
import
import
the
the
state
state
classes
classes
here
here
in
in
the
the
AppModule
appmodule
and
and
add
add
them
them
to
to
the
the
NGXS
ngxs
for
for
root,
root
and
and
then
then
we'll
we'll
also
also
add
add
our
our
NGXS
ngxs
plugins
plugins
here
here
as
as
well.
well
Then
then
just
just
a
a
quick
quick
side
side
note,
note
the
the
plug
plug
in
in
system
system
is
is
really
really
awesome
awesome
because
because
it
it
allows
allows
you
you
to
to
tap
tap
into
into
the
the
state
state
changes
changes
and
and
the
the
action
action
that
that
triggered
triggered
them
them
to
to
extend
extend
the
the
library
library
with
with
your
your
own
own
custom
custom
functionality.
functionality
Now
now
just
just
to
to
do
do
a
a
quick
quick
comparison,
comparison
our
our
app
app
module
module
and
and
ngrx
ngrx
would
would
look
look
more
more
like
like
this
this
where
where
we
we
have
have
a
a
store
store
module
module
for
for
root
root
with
with
a
a
couple
couple
of
of
reducers
reducers
and
and
then
then
an
an
effects
effects
for
for
root
root
with
with
the
the
effects
effects
classes.
classes
Now
now
back
back
to
to
our
our
NGXS
ngxs
app,
app
we're
we're
going
going
to
to
build
build
our
our
first
first
action.
action
An
an
action
action
is
is
just
just
a
a
class
class
that
that
has
has
a
a
type
type
property
property
and
and
an
an
optional
optional
payload.
payload
The
the
only
only
difference
difference
from
from
an
an
ngrx
ngrx
action
action
is
is
that
that
the
the
type
type
property
property
is
is
static.
static
Using
using
a
a
static
static
property
property
here
here
is
is
a
a
clever
clever
way
way
to
to
reduce
reduce
boilerplate
boilerplate
because
because
we
we
don't
don't
actually
actually
have
have
to
to
instantiate
instantiate
an
an
object.
object
We
we
can
can
just
just
pass
pass
in
in
the
the
class
class
name
name
when
when
dispatching
dispatching
an
an
action.
action
Pattern.
pattern
Now
now
I'm
i'm
going
going
to
to
jump
jump
into
into
the
the
app
app
state
state
and
and
that's
that's
where
where
all
all
the
the
action
action
happens.
happens
The
the
very
very
first
first
thing
thing
we'll
we'll
do
do
is
is
model
model
our
our
data
data
as
as
an
an
interface,
interface
which
which
should
should
look
look
very
very
familiar
familiar
if
if
you
you
use
use
NGRX.
ngrx
For
for
the
the
app
app
state,
state
we'll
we'll
set
set
a
a
username,
username
order
order
ID,
id
and
and
a
a
status.
status
The
the
next
next
step
step
is
is
to
to
drop
drop
in
in
the
the
state
state
decorator,
decorator
which
which
replaces
replaces
a
a
reducer
reducer
in
in
ngrx.
ngrx
It's
it's
a
a
class
class
decorator,
decorator
and
and
we
we
can
can
strong
strong
type
type
it
it
to
to
the
the
interface
interface
that
that
we
we
just
just
defined.
defined
Then
then
we'll
we'll
give
give
the
the
state
state
a
a
name
name
so
so
we
we
can
can
slice
slice
it
it
from
from
the
the
global
global
store
store
based
based
on
on
that
that
name.
name
So
so
this
this
will
will
be
be
our
our
app
app
slice,
slice
and
and
we
we
can
can
also
also
pass
pass
it
it
some
some
default
default
values.
values
In
in
this
this
case,
case
I
i
just
just
give
give
it
it
an
an
empty
empty
string
string
and
and
a
a
random
random
number
number
as
as
the
the
order
order
ID.
id
So
so
as
as
you
you
can
can
see
see
here,
here
we
we
now
now
have
have
a
a
slice
slice
of
of
the
the
state
state
that's
that's
clearly
clearly
defined
defined
with
with
default
default
values.
values
The
the
next
next
thing
thing
we'll
we'll
wanna
wanna
do
do
is
is
listen
listen
to
to
actions
actions
and
and
then
then
handle
handle
them
them
as
as
they're
they're
dispatched.
dispatched
For
for
that,
that
we
we
have
have
this
this
Action
action
Decorator
decorator
that
that
takes
takes
the
the
and
and
Class
class
as
as
its
its
argument,
argument
in
in
our
our
case,
case
set
set
username.
username
Then
then
you
you
define
define
a
a
method
method
to
to
handle
handle
this
this
action.
action
The
the
first
first
argument
argument
in
in
this
this
method
method
is
is
the
the
State
state
Context,
context
which
which
allows
allows
us
us
to
to
get
get
and
and
mutate
mutate
the
the
state
state
within
within
this
this
method.
method
In
in
this
this
case
case
here,
here
I'm
i'm
going
going
to
to
use
use
Patch
patch
State
state
to
to
update
update
a
a
single
single
property
property
in
in
the
the
state
state
without
without
updating
updating
other
other
items.
items
Then
then
the
the
second
second
argument
argument
is
is
the
the
action,
action
which
which
may
may
or
or
may
may
not
not
have
have
a
a
payload.
payload
In
in
this
this
case,
case
it
it
has
has
the
the
username
username
as
as
its
its
payload.
payload
At
at
this
this
point,
point
we
we
want
want
to
to
update
update
the
the
current
current
state
state
with
with
the
the
new
new
username,
username
and
and
we
we
can
can
do
do
that
that
by
by
calling
calling
patch
patch
state
state
with
with
the
the
associated
associated
data.
data
In
in
n
n
g
g
r
r
x,
x
normally,
normally
you
you
would
would
compose
compose
a
a
new
new
object
object
by
by
using
using
the
the
spread
spread
syntax
syntax
inside
inside
your
your
reducer
reducer
function.
function
But
but
here,
here
we're
we're
calling
calling
patch
patch
state,
state
which
which
does
does
the
the
same
same
thing
thing
under
under
the
the
hood
hood
but
but
makes
makes
our
our
code
code
a
a
lot
lot
more
more
readable.
readable
And
and
there's
there's
actually
actually
a
a
few
few
other
other
tricks
tricks
that
that
we
we
can
can
do
do
within
within
the
the
state
state
context.
context
Patch
patch
state
state
will
will
only
only
update
update
the
the
properties
properties
that
that
are
are
specified,
specified
but
but
if
if
we
we
want
want
to
to
update
update
everything
everything
within
within
the
the
context
context
of
of
this
this
slice
slice
of
of
the
the
state,
state
we
we
can
can
call
call
set
set
state
state
and
and
that
that
will
will
reset
reset
the
the
state
state
to
to
the
the
new
new
specified
specified
object.
object
We
we
can
can
also
also
dispatch
dispatch
other
other
actions
actions
from
from
inside
inside
this
this
action,
action
which
which
is
is
especially
especially
useful
useful
when
when
you
you
start
start
with
with
asynchronous
asynchronous
data.
data
And
and
the
the
other
other
thing
thing
you
you
can
can
do
do
is
is
you
you
can
can
get
get
the
the
current
current
state
state
as
as
a
a
plain
plain
object.
object
Let's
let's
say
say
we
we
want
want
to
to
look
look
at
at
the
the
current
current
user
user
before
before
we
we
update
update
their
their
username.
username
We
we
just
just
call
call
get
get
state
state
and
and
that
that
gives
gives
us
us
the
the
slice
slice
as
as
a
a
plain
plain
object.
object
Now
now
let's
let's
quickly
quickly
run
run
through
through
a
a
more
more
concrete
concrete
example.
example
Let's
let's
say
say
we
we
have
have
an
an
action
action
that
that
navigates
navigates
with
with
the
the
Angular
angular
router.
router
1st,
1st
we'll
we'll
set
set
up
up
an
an
action
action
called
called
navigate
navigate
with
with
a
a
static
static
read
read
only
only
type,
type
and
and
the
the
payload
payload
is
is
the
the
actual
actual
path
path
that
that
we
we
want
want
to
to
navigate
navigate
to.
to
Then
then
we'll
we'll
set
set
up
up
our
our
state
state
to
to
just
just
be
be
a
a
string
string
where
where
the
the
value
value
represents
represents
the
the
actual
actual
path
path
that
that
the
the
user
user
had
had
navigated
navigated
to.
to
Then
then
we
we
can
can
inject
inject
the
the
Angular
angular
router
router
directly
directly
into
into
our
our
state,
state
which
which
is
is
a
a
really
really
awesome
awesome
feature
feature
of
of
NGXS.
ngxs
One
one
thing
thing
that
that
you
you
really
really
miss
miss
in
in
a
a
reducer
reducer
function
function
is
is
the
the
ability
ability
to
to
use
use
Angular's
angular's
dependency
dependency
injection.
injection
And
and
yet
yet
another
another
cool
cool
feature
feature
is
is
that
that
we're
we're
not
not
just
just
limited
limited
to
to
observables.
observables
The
the
Angular
angular
router
router
returns
returns
a
a
promise
promise
when
when
we
we
navigate.
navigate
So
so
we
we
can
can
actually
actually
just
just
make
make
this
this
an
an
async
async
function,
function
then
then
await
await
the
the
router
router
navigation
navigation
and
and
update
update
the
the
state
state
afterwards.
afterwards
Async
async
await
await
provides
provides
huge
huge
gains
gains
in
in
code
code
readability
readability
and
and
avoids
avoids
the
the
callback
callback
hell
hell
that
that
you
you
would
would
normally
normally
have
have
in
in
an
an
NGRX
ngrx
effect
effect
for
for
dealing
dealing
with
with
a
a
simple
simple
asynchronous
asynchronous
operation
operation
that's
that's
Promise
promise
based.
based
That
that
being
being
said,
said
you
you
can
can
still
still
listen
listen
to
to
a
a
stream
stream
of
of
actions
actions
and
and
handle
handle
them
them
just
just
like
like
you
you
would
would
in
in
an
an
ngrx
ngrx
effect.
effect
What
what
you're
you're
looking
looking
at
at
here
here
with
with
this
this
route
route
handler
handler
is
is
a
a
stream
stream
of
of
actions
actions
that
that
is
is
filtered
filtered
to
to
our
our
navigate
navigate
action.
action
So
so
you
you
do
do
have
have
the
the
option
option
to
to
do
do
things
things
the
the
ngrx
ngrx
effects
effects
way
way
if
if
you
you
prefer
prefer
that,
that
and
and
there
there
are
are
certainly
certainly
use
use
cases
cases
for
for
doing
doing
so.
so
Now
now
that
that
we
we
have
have
all
all
this
this
code
code
in
in
place,
place
let's
let's
go
go
into
into
a
a
component
component
and
and
look
look
at
at
how
how
we
we
can
can
select
select
slices
slices
of
of
the
the
state
state
and
and
dispatch
dispatch
actions.
actions
Let's
let's
say
say
we
we
want
want
to
to
select
select
the
the
app
app
state
state
in
in
our
our
App
app
component.
component
The
the
most
most
familiar
familiar
way
way
to
to
do
do
it
it
is
is
to
to
declare
declare
a
a
property
property
and
and
then
then
inject
inject
the
the
store
store
in
in
the
the
constructor
constructor
and
and
then
then
call
call
store
store
select
select
and
and
use
use
a
a
callback
callback
function
function
to
to
select
select
that
that
slice
slice
of
of
the
the
store.
store
So
so
that's
that's
all
all
good.
good
But
but
in
in
a
a
second
second
here,
here
I'm
i'm
going
going
to
to
show
show
you
you
a
a
much
much
better
better
way
way
to
to
do
do
this
this
with
with
an
an
NGXS
ngxs
Select
select
decorator.
decorator
But
but
first,
first
I
i
wanna
wanna
show
show
you
you
how
how
you
you
can
can
dispatch
dispatch
actions.
actions
To
to
do
do
that,
that
you
you
can
can
simply
simply
call
call
store
store
dispatch
dispatch
and
and
then
then
either
either
pass
pass
in
in
a
a
single
single
action
action
or
or
an
an
array
array
of
of
multiple
multiple
actions.
actions
In
in
this
this
case,
case
we
we
want
want
to
to
set
set
the
the
username
username
and
and
then
then
navigate
navigate
to
to
our
our
lazy
lazy
loaded
loaded
module.
module
That's
that's
cool,
cool
but
but
let's
let's
see
see
if
if
we
we
can
can
make
make
some
some
of
of
this
this
code
code
magically
magically
disappear.
disappear
Let's
let's
delete
delete
everything
everything
from
from
the
the
constructor
constructor
And
and
instead,
instead
we'll
we'll
use
use
the
the
select
select
decorator
decorator
and
and
then
then
point
point
to
to
a
a
property
property
of
of
app
app
followed
followed
by
by
a
a
dollar
dollar
sign.
sign
By
by
convention,
convention
the
the
library
library
will
will
automatically
automatically
look
look
for
for
a
a
property
property
named
named
app
app
minus
minus
the
the
dollar
dollar
sign
sign
on
on
the
the
root
root
store.
store
And
and
that's
that's
all
all
you
you
have
have
to
to
do
do
to
to
get
get
observable
observable
data
data
from
from
the
the
store.
store
But
but
if
if
that's
that's
a
a
little
little
too
too
magical,
magical
you
you
can
can
still
still
pass
pass
a
a
function
function
in
in
to
to
select
select
a
a
slice
slice
as
as
well.
well
The
the
next
next
thing
thing
I
i
wanna
wanna
show
show
you
you
is
is
how
how
to
to
set
set
up
up
lazy
lazy
loading,
loading
which
which
is
is
really
really
easy
easy
to
to
do
do
with
with
NGXS.
ngxs
After
after
the
the
user
user
selects
selects
a
a
name
name
for
for
their
their
order,
order
it's
it's
going
going
to
to
redirect
redirect
them
them
to
to
a
a
lazy
lazy
loaded
loaded
route
route
and
and
update
update
the
the
state
state
with
with
this
this
new
new
data.
data
If
if
we
we
look
look
at
at
the
the
app
app
routing
routing
module,
module
you
you
can
can
see
see
that
that
we
we
have
have
a
a
lazy
lazy
loaded
loaded
salad
salad
module.
module
In
in
order
order
to
to
get
get
this
this
working,
working
We
we
just
just
need
need
to
to
tell
tell
NGXS
ngxs
which
which
state
state
to
to
use
use
inside
inside
this
this
lazy
lazy
module.
module
In
in
this
this
case,
case
we'll
we'll
call
call
NGXS
ngxs
module
module
for
for
feature
feature
and
and
then
then
pass
pass
it
it
the
the
solid
solid
state
state
for
for
this
this
lazy
lazy
module.
module
The
the
implementation
implementation
details
details
for
for
the
the
lazy
lazy
module
module
are
are
very
very
similar
similar
to
to
what
what
we
we
set
set
up
up
in
in
the
the
app,
app
But
but
I
i
still
still
want
want
to
to
show
show
you
you
how
how
selectors
selectors
work
work
when
when
we
we
need
need
to
to
select
select
complex
complex
slices
slices
of
of
the
the
state.
state
This
this
is
is
common
common
when
when
you
you
to
to
do
do
things
things
like
like
client
client
side
side
filtering,
filtering
if
if
you
you
imagine
imagine
you
you
have
have
an
an
array
array
and
and
you
you
wanna
wanna
sort
sort
it
it
alphabetically
alphabetically
or
or
something
something
along
along
those
those
lines.
lines
You
you
can
can
create
create
a
a
selector
selector
by
by
using
using
this
this
selector
selector
decorator
decorator
and
and
then
then
attach
attach
it
it
to
to
a
a
static
static
method.
method
In
in
this
this
example,
example
we'll
we'll
just
just
do
do
something
something
really
really
simple
simple
like
like
transforming
transforming
the
the
dressing
dressing
property
property
to
to
locale
locale
uppercase.
uppercase
Now
now
we
we
can
can
combine
combine
the
the
static
static
method
method
with
with
our
our
select
select
decorator
decorator
in
in
the
the
actual
actual
component.
component
If
if
you
you
remember,
remember
the
the
SelectDecorator
selectdecorator
takes
takes
a
a
function,
function
so
so
we
we
can
can
just
just
pass
pass
it
it
our
our
class
class
followed
followed
by
by
the
the
function
function
name,
name
and
and
then
then
that
that
will
will
select
select
that
that
slice
slice
of
of
the
the
state
state
in
in
whichever
whichever
format
format
we
we
want
want
it.
it
Let's
let's
go
go
ahead
ahead
and
and
compare
compare
this
this
code
code
to
to
ngrx.
ngrx
Building
building
the
the
selector
selector
will
will
look
look
something
something
like
like
this
this
with
with
NGXS
ngxs
on
on
the
the
top
top
and
and
NGRX
ngrx
on
on
the
the
bottom.
bottom
We
we
have
have
the
the
functional
functional
approach
approach
on
on
the
the
bottom
bottom
and
and
the
the
object
object
oriented
oriented
approach
approach
on
on
the
the
top.
top
If
if
you
you
look
look
at
at
how
how
we
we
select
select
state
state
in
in
the
the
component,
component
you
you
can
can
see
see
we
we
get
get
by
by
with
with
about
about
60%
60%
less
less
code
code
in
in
NGXS.
ngxs
The
the
last
last
thing
thing
I
i
wanna
wanna
show
show
you
you
is
is
an
an
asynchronous
asynchronous
action
action
in
in
NGXS.
ngxs
Jumping
jumping
back
back
to
to
the
the
App
app
component,
component
we'll
we'll
create
create
a
a
new
new
action
action
and
and
pass
pass
it
it
this
this
confirm
confirm
order
order
action
action
class.
class
And
and
then
then
notice
notice
I'm
i'm
passing
passing
this
this
cancel
cancel
uncompleted
uncompleted
true
true
option
option
in
in
the
the
action
action
decorator.
decorator
I'll
i'll
show
show
you
you
how
how
this
this
comes
comes
into
into
play
play
in
in
just
just
a
a
second.
second
Inside
inside
this
this
action
action
itself,
itself
we're
we're
going
going
to
to
first
first
patch
patch
the
the
state
state
with
with
an
an
order
order
status
status
of
of
pending.
pending
Then
then
we'll
we'll
return
return
an
an
observable
observable
that
that
represents
represents
the
the
async
async
activity
activity
that
that
we
we
want
want
to
to
perform.
perform
That
that
would
would
most
most
likely
likely
be
be
an
an
API
api
call
call
over
over
the
the
network.
network
But
but
in
in
this
this
case,
case
I'm
i'm
just
just
returning
returning
a
a
mock
mock
observable
observable
that
that
has
has
a
a
5050
5050
chance
chance
of
of
returning
returning
true
true
or
or
false.
false
Inside
inside
the
the
observable,
observable
we'll
we'll
pipe
pipe
in
in
the
the
tap
tap
operator.
operator
If
if
the
the
observable
observable
resolves
resolves
to
to
true,
true
then
then
we'll
we'll
go
go
ahead
ahead
and
and
dispatch
dispatch
the
the
order
order
success
success
action.
action
Otherwise,
otherwise
we'll
we'll
dispatch
dispatch
order
order
failed.
failed
Now
now
if
if
we
we
dispatch
dispatch
this
this
action,
action
it's
it's
going
going
to
to
subscribe
subscribe
to
to
that
that
observable
observable
automatically.
automatically
Normally,
normally
it
it
would
would
subscribe
subscribe
to
to
every
every
single
single
one
one
and
and
resolve
resolve
to
to
a
a
value,
value
But
but
because
because
we
we
added
added
the
the
cancel
cancel
uncompleted
uncompleted
true
true
option
option
in
in
the
the
action
action
decorator,
decorator
it's
it's
going
going
to
to
cancel
cancel
all
all
the
the
previous
previous
requests
requests
automatically.
automatically
It.
it
That's
that's
a
a
pretty
pretty
common
common
requirement
requirement
when
when
you
you
have
have
something
something
like
like
a
a
type
type
ahead
ahead
where
where
you're
you're
making
making
multiple
multiple
asynchronous
asynchronous
API
api
calls.
calls
And
and
this
this
is
is
just
just
one
one
simple
simple
away
away
that
that
the
the
library
library
tries
tries
to
to
make
make
things
things
easier
easier
for
for
you.
you
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
you
you
have
have
any
any
questions
questions
or
or
wanna
wanna
see
see
more
more
NGXS
ngxs
content,
content
please
please
let
let
me
me
know
know
in
in
the
the
comments.
comments
Thanks
thanks
for
for
watching
watching
and
and
I'll
i'll
see
see
you
you
soon.
soon
success
The speakers discuss the use of NGXS, a state management library for Angular, and explain how to create a salad order and import it from NGRX. They also discuss how to create an app and compare it to NGXS Salad Bar, which allows users to create a salad order and adjust the price in response to actions. The speakers then explain how to create a slice of the state, which can be passed in a config file, and how to use the Action Decorator and pass it to update a single property and handle actions. They also show how to set up a route handler and navigate a webpage, and explain how to set up a lazy loading through NGXS Select decorator. They mention a common requirement for multiple asynchronous API calls and encourage viewers to check the NGXS content.
NGXS - Angular State Management
Today, we're going to take a look at NGXS, a new state management library that reimagines the way the Redux should be applied in Angular. It gives us a global immutable data store, then components can select data from the store as an observable, then dispatch actions to mutate the store. The end result is a circular predictable flow of data that is especially beneficial for apps that have a complex data state. In this episode, we'll go through the basics of NGXS from the ground up. If you're new, make sure to like and subscribe and grab the full source code from angularfirebase.com. So first, we need to address the elephant in the room. There's already a state management library for Angular called ngrx, which has become very popular by taking the implementation details of React Redux and applying them to Angular. But the problem is that handler has a type system and makes heavy use of object oriented programming, while React has no type system and makes heavy use of pure functions. In order to strong type everything and maintain a strict separation of concerns in n g r x, we have to write a ton of boilerplate code. Code that is often very difficult to read, especially for someone without an RxJS background. While I'm a big fan of ngrx and one of its top donors, I think NGXS addresses some of these concerns in a very elegant way. So what I've done for this video is I built an app with NGXS and then I built the same exact app with NGRX so we can compare them side by side. The rest of this video will focus on the basics of NGXS, but occasionally, I'll flip over to this ngrx app just so you can see the differences and how the code is implemented. And I'm not recommending one over the other, just showing you a comparison between the 2. The app itself is called NGXS Salad Bar, and it allows the user to create and customize a salad order. If you look at the UI here, you'll see everything highlighted in green is saved in the App Store, and everything with a solid outline border is triggering an action. So you can see here, we trigger actions that add toppings to the salad, and then it computes the price in response to those actions. To get started, we'll generate a new Angular app with the CLI, then we'll install NGXS Store, and also a couple plugins for development so we can use Redux DevTools or console log state changes directly in the browser. The next step is to go into the app module and import NGXS. You'll also notice that I've created a shared folder, which is where we're going to keep the app state and the router state. We're going to build these out later, but you can think of the state as a combination of an ngrx reducer and effect in a single class. Then we'll import the state classes here in the AppModule and add them to the NGXS for root, and then we'll also add our NGXS plugins here as well. Then just a quick side note, the plug in system is really awesome because it allows you to tap into the state changes and the action that triggered them to extend the library with your own custom functionality. Now just to do a quick comparison, our app module and ngrx would look more like this where we have a store module for root with a couple of reducers and then an effects for root with the effects classes. Now back to our NGXS app, we're going to build our first action. An action is just a class that has a type property and an optional payload. The only difference from an ngrx action is that the type property is static. Using a static property here is a clever way to reduce boilerplate because we don't actually have to instantiate an object. We can just pass in the class name when dispatching an action. Pattern. Now I'm going to jump into the app state and that's where all the action happens. The very first thing we'll do is model our data as an interface, which should look very familiar if you use NGRX. For the app state, we'll set a username, order ID, and a status. The next step is to drop in the state decorator, which replaces a reducer in ngrx. It's a class decorator, and we can strong type it to the interface that we just defined. Then we'll give the state a name so we can slice it from the global store based on that name. So this will be our app slice, and we can also pass it some default values. In this case, I just give it an empty string and a random number as the order ID. So as you can see here, we now have a slice of the state that's clearly defined with default values. The next thing we'll wanna do is listen to actions and then handle them as they're dispatched. For that, we have this Action Decorator that takes the and Class as its argument, in our case, set username. Then you define a method to handle this action. The first argument in this method is the State Context, which allows us to get and mutate the state within this method. In this case here, I'm going to use Patch State to update a single property in the state without updating other items. Then the second argument is the action, which may or may not have a payload. In this case, it has the username as its payload. At this point, we want to update the current state with the new username, and we can do that by calling patch state with the associated data. In n g r x, normally, you would compose a new object by using the spread syntax inside your reducer function. But here, we're calling patch state, which does the same thing under the hood but makes our code a lot more readable. And there's actually a few other tricks that we can do within the state context. Patch state will only update the properties that are specified, but if we want to update everything within the context of this slice of the state, we can call set state and that will reset the state to the new specified object. We can also dispatch other actions from inside this action, which is especially useful when you start with asynchronous data. And the other thing you can do is you can get the current state as a plain object. Let's say we want to look at the current user before we update their username. We just call get state and that gives us the slice as a plain object. Now let's quickly run through a more concrete example. Let's say we have an action that navigates with the Angular router. 1st, we'll set up an action called navigate with a static read only type, and the payload is the actual path that we want to navigate to. Then we'll set up our state to just be a string where the value represents the actual path that the user had navigated to. Then we can inject the Angular router directly into our state, which is a really awesome feature of NGXS. One thing that you really miss in a reducer function is the ability to use Angular's dependency injection. And yet another cool feature is that we're not just limited to observables. The Angular router returns a promise when we navigate. So we can actually just make this an async function, then await the router navigation and update the state afterwards. Async await provides huge gains in code readability and avoids the callback hell that you would normally have in an NGRX effect for dealing with a simple asynchronous operation that's Promise based. That being said, you can still listen to a stream of actions and handle them just like you would in an ngrx effect. What you're looking at here with this route handler is a stream of actions that is filtered to our navigate action. So you do have the option to do things the ngrx effects way if you prefer that, and there are certainly use cases for doing so. Now that we have all this code in place, let's go into a component and look at how we can select slices of the state and dispatch actions. Let's say we want to select the app state in our App component. The most familiar way to do it is to declare a property and then inject the store in the constructor and then call store select and use a callback function to select that slice of the store. So that's all good. But in a second here, I'm going to show you a much better way to do this with an NGXS Select decorator. But first, I wanna show you how you can dispatch actions. To do that, you can simply call store dispatch and then either pass in a single action or an array of multiple actions. In this case, we want to set the username and then navigate to our lazy loaded module. That's cool, but let's see if we can make some of this code magically disappear. Let's delete everything from the constructor And instead, we'll use the select decorator and then point to a property of app followed by a dollar sign. By convention, the library will automatically look for a property named app minus the dollar sign on the root store. And that's all you have to do to get observable data from the store. But if that's a little too magical, you can still pass a function in to select a slice as well. The next thing I wanna show you is how to set up lazy loading, which is really easy to do with NGXS. After the user selects a name for their order, it's going to redirect them to a lazy loaded route and update the state with this new data. If we look at the app routing module, you can see that we have a lazy loaded salad module. In order to get this working, We just need to tell NGXS which state to use inside this lazy module. In this case, we'll call NGXS module for feature and then pass it the solid state for this lazy module. The implementation details for the lazy module are very similar to what we set up in the app, But I still want to show you how selectors work when we need to select complex slices of the state. This is common when you to do things like client side filtering, if you imagine you have an array and you wanna sort it alphabetically or something along those lines. You can create a selector by using this selector decorator and then attach it to a static method. In this example, we'll just do something really simple like transforming the dressing property to locale uppercase. Now we can combine the static method with our select decorator in the actual component. If you remember, the SelectDecorator takes a function, so we can just pass it our class followed by the function name, and then that will select that slice of the state in whichever format we want it. Let's go ahead and compare this code to ngrx. Building the selector will look something like this with NGXS on the top and NGRX on the bottom. We have the functional approach on the bottom and the object oriented approach on the top. If you look at how we select state in the component, you can see we get by with about 60% less code in NGXS. The last thing I wanna show you is an asynchronous action in NGXS. Jumping back to the App component, we'll create a new action and pass it this confirm order action class. And then notice I'm passing this cancel uncompleted true option in the action decorator. I'll show you how this comes into play in just a second. Inside this action itself, we're going to first patch the state with an order status of pending. Then we'll return an observable that represents the async activity that we want to perform. That would most likely be an API call over the network. But in this case, I'm just returning a mock observable that has a 5050 chance of returning true or false. Inside the observable, we'll pipe in the tap operator. If the observable resolves to true, then we'll go ahead and dispatch the order success action. Otherwise, we'll dispatch order failed. Now if we dispatch this action, it's going to subscribe to that observable automatically. Normally, it would subscribe to every single one and resolve to a value, But because we added the cancel uncompleted true option in the action decorator, it's going to cancel all the previous requests automatically. It. That's a pretty common requirement when you have something like a type ahead where you're making multiple asynchronous API calls. And this is just one simple away that the library tries to make things easier for you. I'm gonna go ahead and wrap things up there. If you have any questions or wanna see more NGXS content, please let me know in the comments. Thanks for watching and I'll see you soon.
The speakers discuss the use of NGXS, a state management library for Angular, and explain how to create a salad order and import it from NGRX. They also discuss how to create an app and compare it to NGXS Salad Bar, which allows users to create a salad order and adjust the price in response to actions. The speakers then explain how to create a slice of the state, which can be passed in a config file, and how to use the Action Decorator and pass it to update a single property and handle actions. They also show how to set up a route handler and navigate a webpage, and explain how to set up a lazy loading through NGXS Select decorator. They mention a common requirement for multiple asynchronous API calls and encourage viewers to check the NGXS content.