I'm trying to add a new field called totalElements to the entity collection state in NgRx Data. This field represents the total number of rows returned by a backend table.
I've gone through the instructions on how to add this field in the official documentation, but I'm having trouble figuring out how to use this new field in my components and services.
Can anyone provide guidance on how to read and update this new totalElements field in NgRx Data?
I have successfully retrieved and stored the entities from the backend in the store, but I am now faced with the challenge of implementing pagination in my component. To do this, I need to store the totalElements property.
The backend response looks like this:
{
totalElements: 100,
content: [{id: 1, ...}, {id: 2, ...}]
}
In entity-metadata.ts, I added the following:
const entityMetadata: EntityMetadataMap = {
Patient: {
additionalCollectionState: {
totalElements: 0,
},
},
};
I also added the following as instructed in the official documentation:
//Step 1: Implement PersistenceResultHandler to save data from backend to action.payload
export class AdditionalPersistenceResultHandler extends DefaultPersistenceResultHandler {
override handleSuccess(originalAction: EntityAction): (data: any) => Action {
const actionHandler = super.handleSuccess(originalAction);
// return a factory to get a data handler to
// parse data from DataService and save to action.payload
return (data: any) => {
const action = actionHandler.call(this, data);
if (action && data && data.totalElements) {
(action as any).payload.totalElements = data.totalElements;
}
return action;
};
}
}
// Step 2: Overwrite EntityCollectionReducerMethods to save the additional property from action.payload to the EntityCollection instance
export class AdditionalEntityCollectionReducerMethods<T> extends EntityCollectionReducerMethods<T> {
constructor(
public override entityName: string,
public override definition: EntityDefinition<T>
) {
super(entityName, definition);
}
protected override queryAllSuccess(
collection: EntityCollection<T>,
action: EntityAction<T[]>
): EntityCollection<T> {
const ec = super.queryAllSuccess(collection, action);
if ((action.payload as any).totalElements) {
// save the totalElements property from action.payload to entityCollection instance
(ec as any).totalElements = (action.payload as any).totalElements;
}
return ec;
}
}
@Injectable()
export class AdditionalEntityCollectionReducerMethodsFactory {
constructor(private entityDefinitionService: EntityDefinitionService) {}
/** Create the {EntityCollectionReducerMethods} for the named entity type */
create<T>(entityName: string): EntityCollectionReducerMethodMap<T> {
const definition = this.entityDefinitionService.getDefinition<T>(entityName);
const methodsClass = new AdditionalEntityCollectionReducerMethods(entityName, definition);
return methodsClass.methods;
}
}
I also updated the NgModule as below:
...
providers: [
{
provide: PersistenceResultHandler,
useClass: AdditionalPersistenceResultHandler,
},
{
provide: EntityCollectionReducerMethodsFactory,
useClass: AdditionalEntityCollectionReducerMethodsFactory,
},
],
...
Everything is compiled okay and I can see 'totalElements: 0' in the entity collection store as expected.
{
entityCache: {
Patient: {
ids: ['1', '2', ...],
entities: {1: {...}, 2: {...}, ...},
entityName: 'Patient',
filter: '',
loaded: true,
loading: false,
changeState: {},
totalElements: 0
}
}
}
Unfortunetly, I don't know how to update the totalElements (from backend) and how to access it from my component.
This is my data service implementation. I want to update the totalElements from the getAll() method.
@Injectable()
export class PatientService extends DefaultDataService<PatientModel> {
constructor(
http: HttpClient,
httpUrlGenerator: HttpUrlGenerator,
private graphqlService: GraphqlService) {
super('Patient', http, httpUrlGenerator);
}
override getAll(): Observable<PatientModel[]> {
return this.graphqlService.sendQuery(`
query patient_page {
patientsByPage(page: 0, size: 10) {
totalElements
content {
id
mrNumber
fullName
dateOfBirth
gender
email
active
profilePicture
}
}
}
`).pipe(map((response: any) => {
// can I set the totalElements here?
// ..... ????
return response.data.patientsByPage.content
}));
}
}
Then from my component, I want to access it like this:
this.myCollectionService.totalElements
Thank you in advance for any assistance you can provide. I greatly appreciate your help.