Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ngrx-data select a single entity

I am using ngrx-data plugin (runs on top of ngrx), and I'm trying to select a single entity from the store (that ngrx data calls 'Cache'). I found that you can add a single entity to the cache but I can't find the way to retrieve a single item (based on Id) from the store.

Do I have to write my own selector for this? I would assume a simple operation like this would be provided by ngrx-data

like image 437
maury844 Avatar asked Aug 30 '19 19:08

maury844


People also ask

What is a good use case for NgRx entity?

business data, such as for example Courses or Lessons, in the case of an online course platform. some UI state, such as for example UI user preferences.

When should I use NgRx data?

Quoting NgRx Data documentation, typical usage of this library is entity data management. Basically it means that if you have complex entity collection you should go hard way and use @ngrx/entity where the boilerplate code is huge.


Video Answer


3 Answers

I am sure there is a more elegant way to do this, but I was able to get a single entity by using the collection$ property on the data service.

for example, I have an entity called Core and an EntityService called CoreEntityService. My entity cache has been populated through the coreEntityService.getByKey(id). Or I could have populated the entity cache by a getAll().

when I want to retrieve the core with that id I use this construct, illustrated here by logging the single entity to the console:

this.coreEntityService.collection$.subscribe(collection => console.log(collection.entities[id]))

Edited to Add:

you can also subscribe to entity service's entityMap$. I added a method to my entity service called selectEntityById like this which works well and returns an observable, unlike the previous code, which returns an actual object:

selectEntityById(coreId: number): Observable<Core> {
return this.entityMap$.pipe(
  map(entities => entities[coreId]),
  first());
}

The documentation for ngrx/data is not great at the moment but it is improving. I'm hoping that someone will post a better answer to this question soon.

like image 167
glitchbane Avatar answered Oct 09 '22 00:10

glitchbane


I had the same question and arrived at a slightly different result. This is not necessarily any better than the other answer, but it does work in a slightly different manner.

Just as glitchbane said in his answer, the documentation is a work in progress so I am also hoping that I am missing some readily available method to do this provided by ngrx-data, but I have yet to find one.

I wanted my subscription to provide the single element I was looking for rather than using the id to select the element inside the subscription. This lead me to creating a selector.

Imports and Selector:

import { createSelector } from '@ngrx/store';
import { EntityCollection } from '@ngrx/data';
import { MyModel } from '....my.model';

export const selectMyModels =
    (entities: EntityCollection<MyModel>) => entities.entities;

export const selectMyModelById = (id: number) => createSelector(
    selectMyModels,
    entities => entities[id]
);

Example usage:

this.myModelEntityCollectionService.collection$.pipe(
    select(selectMyModelById(1)))                    // <-- used here
        .subscribe((myModel: MyModel) => {
            this.myLogger.log(JSON.stringify(myModel));
        }
);
like image 2
jhoe Avatar answered Oct 09 '22 00:10

jhoe


I start using Ngrx-data not along time ago...I supposed you can create selectors in other ways.

However, I will explain how I used to do for entities coming directly from our model, cache and so on ... What I am doing is importing the service in the constructor

  constructor(private myModelsService: myModelEntityService) { } 

And then for example getting all the entities with

ngOnInit(){
    this.entities$ = this.myModelsService.entities$;
}

Finally, to solve your problem that it is just to take a saved entity from your store or as is the same rescuing from the observable of entities; I would catch the entity up like below

this.myEntity$ = this.myModelsService.entities$.pipe(mergeAll(), take(n), last())

Basically, your are doing an emission for every entities with mergeAll (decomposing an array), cutting them with take and setting the "n" that you want (let's say you need the third element, then n="3") and completing the emissions with last so you just have this element.

I hope it helps you or may give you the right direction.

like image 1
ackuser Avatar answered Oct 08 '22 23:10

ackuser