0

I have a call where I get a list of Ids of person who have outstanding reports to file, and I want to keep track of the amount of reports that person has outstanding. I'm storing that data using EntityAdapter. Now I can't figure out how to keep count in the adapter.

So far I've checked the ngrx docs, tried quite a few manipulations to the code and asked my question on the gitter chat room, with no result so far.

My service returns an array of strings, which contains the id of the person. Example data could be:

Array of person IDs

Here I have the same Id twice, which means that person has 2 reports. I want to store that Id and keep count '2'. At the moment I'm using this code for the adapter:

    export interface State extends EntityState<string> {
      showRegistrations: boolean,
      loading: boolean,
      loaded: boolean,
    }

    export const adapter: EntityAdapter<string> = createEntityAdapter<string>({
      selectId: (item: string) => item,
      sortComparer: false,
    });

    export const initialState: State = adapter.getInitialState({
      showRegistrations: true,
      loading: false,
      loaded: false,
    });

This gives me in my store following result:

store result

But I'm actually looking for following result, where each Id is stored and I know how many times that Id was found specifically:

enter image description here

James D
  • 1,975
  • 2
  • 17
  • 26
  • I think you’ll need a custom reducer for this. The first entity will now just be overwritten by the second (which is what you usually want). – MikeOne Oct 02 '19 at 16:38
  • I think you should be able to just use `Effects` to manipulate the object so it would hold a property "OutstandingReports" for each Ids – penleychan Oct 02 '19 at 16:52

2 Answers2

0

@ngrx/entity is aimed to store and retrieve entities based on an id. The use case that you're describing is not fitted for @ngrx/entity.

timdeschryver
  • 14,415
  • 1
  • 19
  • 32
0

In follow up on Tim's answer I looked outside the box of ngrx/entity. I shouldn't really have focused on using it in the first place as the answer was pretty easy.

I added an interface which holds a string and a number. In my code I called this ReportCount. Then in the loadsuccess action I either add a new reportCount with the Id of the user and set count to 1, or I add 1 to count.

Eventually I ended up with following code which works as expected:

(I'm posting this for other people who might get stuck on the same issue)


export interface ReportCount{
  superintendent: string,
  count: number,
};


export interface State {
  reportCounts: ReportCount[],
  showRegistrations: boolean,
  loading: boolean,
  loaded: boolean,
};

export const initialState: State = {
  reportCounts: [],
  showRegistrations: true,
  loading: false,
  loaded: false,
};

export const reducer = createReducer(
  initialState,
  on(RegistrationActions.ShowRegistrations,
    (state, { setShow }) => ({
      ...state,
      showRegistrations: setShow,
    })
  ),

  on(RegistrationSuperintendentsCollectionActions.loadRegistrationSuperintendentCollection, (state) => ({
    ...state,
    loading: true,
  })),
  on(RegistrationSuperintendentsCollectionApiActions.loadRegistrationSuperintendentsSuccess,
    (state, { superintendents }) => {
      const repCount: ReportCount[] = [];
      superintendents.forEach(superintendent => {
        let sup = repCount.find(s => s.superintendent === superintendent);
        sup ? (sup.count = sup.count + 1) : repCount.push({superintendent, count:1});
      })
      return ({
        ...state,
        reportCounts: repCount,
        loading: false,
        loaded: true
      })
    }
  ),
);

export const getShowRegistrations = (state: State) => state.showRegistrations;

export const getLoaded = (state: State) => state.loaded;

export const getLoading = (state: State) => state.loading;

export const getLoadedSuperintendentRegistrations  = (state: State) => state.reportCounts; 
James D
  • 1,975
  • 2
  • 17
  • 26