Search code examples
angulartypescriptdictionaryngrxngrx-entity

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


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.


Solution

  • @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.