Transforming data from the store so that it works in our feature components can be a bit clunky and certainly not something that we would want to repeat for every single component that consumes state. Thankfully we have the ability to predefine specific "slices" of state that we want to query from the store and express them in the form of ngrx selectors. Selectors are essentially functions that take state as an input and returns the part of the state that we want in the shape we require. In this lesson, we will build out some basic low-level selectors at our feature reducer as we utilize some very helpful selectors that ngrx entity provides for us right out of the box. We will then create high-level selectors at our top-level reducer that can be consumed across our application and see how it makes selecting state from our state so much easier to read.
Instructor: [00:00] In this lesson, we're going to learn how to simplify querying slices of state off of our NgRx Store using selectors. If we look in our projects component, what we have is a fairly interesting observable sequence, where we're selecting the projects feature, but we're also having to do some additional data manipulation to get our data in the shape that we want so that it is consumable by the template.
[00:32] Using selectors, we can replace this type of data manipulation at the component level and replace it with these composable functions that essentially serve to query the state of a feature or an application.
[00:57] If we hop into our projects reducer, because we're using NgRx entity, we have some selectors that are available to us. We're starting in the projects reducer, because we're going to produce some low-level selectors that expose just the bare minimum to provide essentially our project's state.
[01:21] The first one we're going to do is we're going to create a method called getSelectedProjectId. Then from here, this is just a simple function that is going to take application state, and then return the selected project ID of our application state. This is very much like the map function that we saw in the projects component.
[01:48] From here, we're going to use destructuring to pull some available selectors off of the adaptor.getSelectors method. We're going to call adapter.getSelectors. From here, we can destructure and define selected IDs, selected entities, and select all.
[02:20] Because these are fairly generic select ID, select entity, select all, we will then remap them to a more descriptive name such as select project IDs, select project entities, and as well select all entities, or rather select all projects.
[02:43] Once we have defined the selectors at the future reducer level, then we can hop into out top-level reducer and we can define the selectors that we want to make available to the entire application.
[02:58] Just above this customer selectors, we will create a new comment block and we'll call this project selectors. Within this, we're going to define a feature selectors. This just allows us to essentially grab a slice of state of the store that specifically scoped to a feature. In this case, it's going to be project.
[03:20] We'll go ahead and export const select projects state. Now, we're going to call createFeatureSelector. Then, we're going to type this to fromProjects.projectState. Then because this is a method that we're going to call it with a parameter of "projects". Is we're just saying give us this specific slice of the state and scope it as a feature.
[03:51] Now that we have our feature selector defined, from there, we're going to define our selectors for select IDs, select entities, and select all projects, so we'll go selectProjectIds. We'll go createSelector. Now, this is going to take two parameters.
[04:12] The first one being the entire state for that feature, so select projectState. Then, we're going to pull in our low-level selector from projects.selectProjectIds. Now, we'll go ahead and take this. We'll paste this two more times. Now within this, we'll update this to select project entities.
[04:40] We will update this here. Oh, I think I may have a typo. Let's fix that real quick. There we go. All right. Back into the source, select project entities. We can go in and do select all projects as well, so select all projects as well.
[05:04] Select all projects, and then we'll also use the select all projects from the low-level reducer. Once we have these defined, we will go ahead and hop into our barrel roll here. We'll make these available by exporting them.
[05:26] This is simply I think the surface area for this is once available within our state module, but because we're using in a next workspace that it creates some really nice named like workspaces that we could import this in, but we're having to expose these pieces as we want to consume them.
[05:49] We'll go ahead and add in the select all projects selector. We'll go down to our observable sequence here. We're going to replace this select projects with this selector. Now, all of the heavy lifting and the manipulation is happening in the selector at the reducer level.
[06:13] We saw that that was working, that we're able to select our projects. It was able to then iterate our projects collection. Just to do a recap, that because we're using NgRx entity, that we were able to define some low-level selectors, that we then made available in our top-level reducer, so that this is what we will call is we interact with the state.
[06:46] This is useful if we want to actually combine selectors from different data models within your application. Then from there, we went ahead and took the feature selectors, the sub selectors, and we exported the select all project, so it's available for application.
[07:06] Then, we hopped into the projects component and we replace that complex observable stream sequence with a simple selector moving that logic into the state management portion. This is how you integrate NgRx selectors into your application.