Connect Related Angular Data Models with Computed Data using ngrx Selectors

InstructorLukas Ruebbelke

Share this video with your friends

Send Tweet

Redux, and by extension ngrx, generally promotes a normalized data structure with each distinct entity in the domain model being segmented into its own reducer. This is all well and good but what happens when you have two entities in your application that are related and you need to display them together as a single data structure in your application? Outside of asynchronous operations, handling relational data can be one of the most challenging aspects when learning ngrx. Not only can we use selectors to query state from our store but we can use them to dynamically compute data on the fly as it is consumed by our components. By exposing our high-level selectors at our top-level reducer this makes it easy to combine selectors from related entities and transform and return data to our components. In this lesson, we will start off with a simple example of how to use a selector to produce computed data based on a condition and then move on to how combine related entities in a single selector.

massimo-ua
~ 6 years ago

Is this solution (computed data) applicable in case when you have a lot of data and only part of this data is actually used by user (long list or table with pagination)? I mean what if you need to display 5k users with their own projects (10k) and user interacts in the same time only with about from 10 to 100 records. So to use computed data you have to hold all users and projects records in the store.

Lukas Ruebbelkeinstructor
~ 6 years ago

Typically when I run into these scenarios, it is indicative of a UX problem. I cannot think of a reasonable scenario where someone would need to display 5k of anything at a single time to a user. How could a user even process that information? With that said, I DO recommend implementing a pagination strategy for large data collections at the store and only pull in enough data to satisfy the user experience within the context of the business domain.

massimo-ua
~ 6 years ago

Thanks for quick reply Lukas. We use pagination in our project and in store holds only data that correspond to one page of data. But in my case I decided to pull from backend list of users populated with their projects (every user has property "projects" that holds list of his projects). In that case I do not need to combine data on frontend. But in the same time I need to hold in store separate additional list of projects to have ability to manipulate with their properties. Is it correct (part of projects data is duplicated in store)?

Lukas Ruebbelkeinstructor
~ 6 years ago

Are you normalizing your data?

massimo-ua
~ 6 years ago

Sorry for such a long list of questions but that is actually what I am asking about. Should I always keep my data in store 100% normalized or there are cases when it is not necessary?

Lukas Ruebbelkeinstructor
~ 6 years ago

I recently read a blog post where the author had seen a significant increase in performance by NOT normalizing their data. This goes back to the class relational vs nosql database conundrum where one is really good at writing data where the other one is really good at reading data. To answer your question, you do not have to follow are guideline or rule just for the sake of being "compliant". Our job is to provide value to our organization and customers and sometimes there are good reasons to prioritize them over "purity". I would just suggest that you fully understand your domain and the tradeoffs you are making and then make the best long term decision for the project. For instance, if you're application is primarily a read-only style application, NOT normalizing your data may be a good choice for performance reasons.

Oscar Lagatta
~ 6 years ago

Hi Lukas,

are you showing the computed data in the application somehow ? how you manipulate the data returned in the component to display parent child relations?

thanks

Lukas Ruebbelkeinstructor
~ 6 years ago

Hey Oscar, No, that last one was just to show you could build computed data in the selector. As far as actually displaying it in the UI, my go-to generally a nested table or accordion structure.

Wilgert Velinga
~ 5 years ago

Why are you wrapping a spread operator in Object.assign?

Does not make much sense, because TypeScript already turns a spread operator into Object.assign. See this TypeScript Playground