3

I am trying to use @ngrx/data to create a simple service in Angular, and am receiving the error EntityDefinition for entity type "Position". when the component runs.

My EntityMetadataMap is this:

const entityMetaData: EntityMetadataMap = {
  Employee: {},
  Position: {}
};

const pluralNames = { Employee: 'Employees', Position: 'Positions' };

export const entityConfig = {
  entityMetaData,
  pluralNames,
};

and my store module is this:

@NgModule({
  declarations: [],
  imports: [
    StoreModule.forRoot({}),
    EffectsModule.forRoot([]),
    StoreDevtoolsModule.instrument(),
    EntityDataModule.forRoot(entityConfig),
  ],
  providers: [
    {provide: DefaultDataServiceConfig, useValue: defaultDataServiceConfig},
    PositionsDataService
  ]

})
export class ItwStoreModule {
  constructor() {
    console.log(entityConfig);
  }
}

and my data service for position is this:

@Injectable({ providedIn: 'root' })
export class PositionsDataService extends EntityCollectionServiceBase<Position> {
  constructor(serviceFactory: EntityCollectionServiceElementsFactory) {
    super('Position', serviceFactory);
  }
}

I can put a break point in the module setup and in EntityDataModule and I can see that the entity definition exists and is getting set correctly (as part of EntityDataModule.forRoot(entityConfig).

But when the constructor of the service fires and calls super(...), in the debugger, I can see that there are no EntityDefinitions in the EntityCollectionServiceElementsFactory that is passed in (note the "definitions" are empty):

enter image description here

What am I doing wrong here? Obviously, between when the store module is initiated and when the dependency injection injects the EntityCollectionServiceElementsFactory into the service, something is going wrong.

CleverPatrick
  • 9,261
  • 5
  • 63
  • 86
  • I don't understand your intention behind. Do you want to create a store with entities ? – Wandrille Nov 06 '19 at 13:32
  • pretty much, yes. I was looking at the various options and it seems ngrx/data handles a lot of boilerplate code for you. But obviously I'm missing something (I've looked around at every example I can find and can't spot what I'm missing). – CleverPatrick Nov 06 '19 at 16:37
  • 1
    [Stackblitz reproduction of the error](https://stackblitz.com/edit/angular-so58731183-reproduce-error) – Andrew Allen Nov 06 '19 at 18:27

3 Answers3

3

You have a typo:-

It should be entityMetadata

Andrew Allen
  • 6,512
  • 5
  • 30
  • 73
  • 1
    OMG. That worked. My first thought was, "it's just a variable name, who cares"... then I realized I was using property shorthand in the export! GAH. Thank you so much. I had just given up on using ngrx/data at that point! – CleverPatrick Nov 06 '19 at 20:22
  • If you get this error, and have no typo, then pay attention to correctly import the module which initializes the providers of your ngrx/data services. Ex: If you have an Article component using entityMetadata "Articles" and you want to use Articles operations (add, update etc) it in another component, MyAwesomeComponent for instance, you have to import ArticleModule into MyAwesomeComponentModule. – loquace Dec 07 '21 at 18:04
2

To work easily with entities, here is an example

In your store.states.ts

export interface State {
    store_A: STATE_A;
}

export interface STATE_A extends EntityState<ClassA> {}

export const adapter: EntityAdapter<ClassA> = createEntityAdapter<ClassA>({
    selectId: (params: ClassA) => params.id
});

export const initialState: State = {
    store_A: aAdapter.getInitialState({})
};

In your store.selector.ts

export const getMainState = createFeatureSelector<State>('root-feature');

export const getStateA = createSelector(getMainState , (state) => state.stateA);

export const getAllStateA = createSelector(getStateA , (state) => adapter.getSelectors().selectAll);

In your service or component:

this.store.select(getAllStateA) // Observable of all item A

In your reducer:

...
  on(
    MyAction,
    (state, { itemAs }) => {
      return adapter.addAll(itemAs , { ...state });
    }
  ),
...
Wandrille
  • 6,267
  • 3
  • 20
  • 43
  • 2
    This is not an answer - you're using `@ngrx/entities` alone and not the wrapper `@ngrx/data` OP is asking for (along with a specific error). – Andrew Allen Nov 06 '19 at 18:03
1

While providing the config, be sure to use property name entityConfig. For example:

const mySampleEntityMetadata : EntityMetadataMap = {
    Hero: {},
    Villain: {}
};

...

export const entityConfig = {
    entityMetadata: mySampleEntityMetadata,
    pluralNames
};
Amit
  • 25,106
  • 25
  • 75
  • 116