I created a custom DataService ngrx/entity that extends the NGRX DefaultDataService, I need to get to a custom URL which returns a Json Object. However I haven't been able to register my Custom DataService as I have no modules installed and haven't found any way to register the service so the override never happens. Anyone else having this issue? Installed:
"@angular/animations": "^18.2.0",
"@angular/cdk": "^18.2.0",
"@angular/common": "^18.2.0",
"@angular/compiler": "^18.2.0",
"@angular/core": "^18.2.0",
"@angular/forms": "^18.2.0",
"@angular/material": "^18.2.0",
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/platform-server": "^18.2.0",
"@angular/router": "^18.2.0",
"@angular/ssr": "^18.2.0",
"@coreui/angular": "^5.2.14",
"@ngrx/data": "^18.0.2",
"@ngrx/effects": "^18.0.2",
"@ngrx/entity": "^18.0.2",
"@ngrx/router-store": "^18.0.2",
"@ngrx/store": "^18.0.2",
"@ngrx/store-devtools": "^18.0.2",
"express": "^4.18.2",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.10"
This is my entity-metadata.ts file:
import {
EntityMetadataMap,
EntityDataModuleConfig,
} from '@ngrx/data';
const entityMetadata: EntityMetadataMap = {
Country: {}
};
const pluralNames = { Country: 'Countries' };
export const entityConfig: EntityDataModuleConfig = {
entityMetadata,
pluralNames
};
here is my app.config.ts
import {ApplicationConfig, provideZoneChangeDetection, isDevMode} from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import {provideStore} from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import * as fromApp from './store/app.reducer';
import {provideClientHydration} from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideHttpClient } from '@angular/common/http';
import { provideStoreDevtools } from '@ngrx/store-devtools';
import {AuthEffects} from "./pages/auth/store/auth.effects";
import { provideRouterStore } from '@ngrx/router-store';
import {provideEntityData, withEffects} from '@ngrx/data';
import {entityConfig} from './entity-metadata';
export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideClientHydration(),
provideAnimationsAsync(),
provideStore(fromApp.appReducer, { runtimeChecks: {
strictActionImmutability: true
} }),
provideHttpClient(),
provideEffects(AuthEffects),
provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
provideRouterStore(),
provideEntityData(entityConfig, withEffects())
]
};
Even though I have providedIn: 'root' on this DataService it still isn't being invoked. Here is my Custom DataService file:
import { Injectable } from '@angular/core';
import {DefaultDataService, HttpUrlGenerator} from "@ngrx/data";
import {Countries, Country} from "../../../models/countries.model";
import {HttpClient} from "@angular/common/http";
import {map, Observable} from "rxjs";
import {baseUrl} from "../../../../../environments/environments";
@Injectable({
providedIn: 'root'
})
export class CountryDataService extends DefaultDataService<Country>{
constructor(http:HttpClient, httpUrlGenerator:HttpUrlGenerator) {
super('Country', http, httpUrlGenerator);
}
override getAll(): Observable<Country[]> {
return this.http.get<Countries>(baseUrl + '/api/country/GetCountries')
.pipe(
map(res => res["COUNTRIES"])
)
}
}
my resolver:
import { Injectable } from '@angular/core';
import {
ActivatedRouteSnapshot,
Resolve,
RouterStateSnapshot,
} from '@angular/router';
import { map, Observable } from 'rxjs';
import { CountryEntityService } from './country-entity.service';
import {CountryDataService} from "./country-data.service";
import {CountryActions} from './action-types';
@Injectable({ providedIn: 'root' })
export class CountryResolver implements Resolve<boolean> {
constructor(
private countryService: CountryEntityService
) {}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> {
return this.countryService.getAll().pipe(map((countries) => !!countries));
}
}
YOu could register the new service on the AppComponent
which is the root of the application.
@Component({
...
imports: [ ... ],
providers: [ HeroDataService ] // <-- provide the data service
})
export class AppComponent {
constructor(
entityDataService: EntityDataService,
heroDataService: HeroDataService,
) {
entityDataService.registerService('Hero', heroDataService); // <-- register it
}
}
You could also use the app_initializer
method to initialize the service.
export function initializeApplication(entityDataService: EntityDataService, heroDataService: HeroDataService) {
return (): void => {
entityDataService.registerService('Hero', heroDataService); // <-- register it
});
}
export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideClientHydration(),
provideAnimationsAsync(),
provideStore(fromApp.appReducer, { runtimeChecks: {
strictActionImmutability: true
} }),
provideHttpClient(),
provideEffects(AuthEffects),
provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
provideRouterStore(),
provideEntityData(entityConfig, withEffects()),
{
provide: APP_INITIALIZER,
useFactory: initializeApplication,
multi: true,
deps: [EntityDataService, HeroDataService],
},
]
};