Angular18独立配置中如何注册自定义DataService重写GetAll方法?
问题描述
我基于NGRX/Entity创建了继承自DefaultDataService的自定义DataService,用来请求自定义URL获取JSON数据。但因为用的是Angular独立配置(无NgModule),没法注册这个自定义服务,导致重写的getAll方法从来没生效过。
相关依赖版本:
{ "@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" }
entity-metadata.ts 文件内容
import { EntityMetadataMap, EntityDataModuleConfig, } from '@ngrx/data'; const entityMetadata: EntityMetadataMap = { Country: {} }; const pluralNames = { Country: 'Countries' }; export const entityConfig: EntityDataModuleConfig = { entityMetadata, pluralNames };
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()) ] };
自定义DataService 文件内容
虽然已经设置了providedIn: 'root',但服务仍未被调用:
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"]) ) } }
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)); } }
解决方案
在Angular独立配置中,NGRX Data不会自动发现自定义的DefaultDataService实现,即使你加了providedIn: 'root'。需要手动把自定义服务注册到NGRX Data的配置里,具体操作如下:
修改entity-metadata.ts,为Country实体指定dataService
在entityMetadata的Country配置中添加dataService属性,指向自定义的CountryDataService:import { EntityMetadataMap, EntityDataModuleConfig, } from '@ngrx/data'; // 引入自定义服务 import { CountryDataService } from './path-to-your-service/country-data.service'; const entityMetadata: EntityMetadataMap = { Country: { dataService: CountryDataService // 指定自定义数据服务 } }; const pluralNames = { Country: 'Countries' }; export const entityConfig: EntityDataModuleConfig = { entityMetadata, pluralNames };在app.config.ts中注册DataService
需要用provideDataService函数把自定义服务添加到providers数组中,这个函数来自@ngrx/data: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, provideDataService} from '@ngrx/data'; // 引入provideDataService import {entityConfig} from './entity-metadata'; import { CountryDataService } from './path-to-your-service/country-data.service'; // 引入自定义服务 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()), provideDataService(CountryDataService) // 注册自定义数据服务 ] };验证是否生效
运行项目后,当CountryEntityService.getAll()被调用时,应该会触发你自定义的getAll方法,请求指定的URL。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

