angular NGRX: Not able to select single value in ngrx entity based on id

3.5k Views Asked by At

I am trying to select an object by Id from the entity state. Below is my reducer.

 export interface MessageState extends EntityState<Message> {
  // additional entities state properties
  loaded: boolean;
  loading: boolean;
}

export const adapter: EntityAdapter<Message> = createEntityAdapter<Message>({
  selectId: (msg: Message) => msg.messageId,
});

export const initialState: MessageState = adapter.getInitialState({
  // additional entity state properties
  loaded: false,
  loading: false,
});

export function reducer(state = initialState, action: MessageActionsUnion): MessageState {
  switch (action.type) {

    case MessageActionTypes.UPSERT_Message: {
      return { ...state, loading: true, loaded: false };
    }

    case MessageActionTypes.UPSERT_Message_SUCCESS: {
      return adapter.upsertOne(action.payload.Message,
        {
          ...state, loaded: true, loading: false,
        });

    }

    default: {
      return state;
    }
  }
}

Below is my index.ts file

export interface State extends fromRoot.AppState {
  queueModule: QueueState;
}

export interface QueueState {
  msgHeaders: fromMsgHeaders.MessageHeaderState
}

export const reducers: ActionReducerMap<QueueState> = {
  msgHeaders: fromMsgHeaders.reducer

};

export const getQueueState$ = createFeatureSelector<QueueState>('queueModule');

I am trying to form a selector when passed an Id will return the value from the entity.

    export const selectMessages = createSelector(
      fromFeatures.getQueueState$,
      (state: fromFeatures.QueueState) => state.msgs
    );

    export const {
      selectAll: selectAllMessages,
      selectEntities: selectMessagesEntities,
      selectIds: selectMessagesIds,
      selectTotal: selectMessagesTotal
    } = adapter.getSelectors(selectMessages);

I looked at many resources, but none are clear on how to select an object by passing the id.

2

There are 2 best solutions below

0
On BEST ANSWER

@ngrx/entity does provide a getEntityValueById after their release of v6.1.0 (ngrx entity changelog) where they have introduced dictionary.

Thus using this, I was able to pull a single value of an entity by its id in the below way.

// in the selector
import { Dictionary} from '@ngrx/entity;

export const getMessageById = () => {
  return createSelector(
    selectMessagesEntities,                
    (entities: Dictionary<Message>, props: { messageId: number }) => {
      return entities[props.messageId];
    },
  );
};


//to call the selector


this.msg$ = this.store.pipe(select(
      fromStore.getMessageById(), { messageId: 10 }
    )).pipe(
      map(
        (message: Message) => {
          return this.msg = message;
        },
      )
    );

Also a great reference for this approach has been documented here.

2
On

@ngrx/entity doesn't provide a getOneById selector.

In most of the cases, this is something you shouldn't have to do.

That being said there are ways of creating a selector which does exactly this, for more info see (NgRx: Parameterized selectors)[https://blog.angularindepth.com/ngrx-parameterized-selector-e3f610529f8].

For example:

export const getCount = createSelector(
  getCounterValue, 
  (counter, props) => counter * props.multiply
);

export const selectCustomer = (id: string) => createSelector(
  selectCustomers,
  customers => customers[id]
);