dependency injection - providedin - ¿Cómo extender un componente con inyección de dependencia en Angular 2?
inyeccion de dependencias angular 6 (3)
Tengo la siguiente clase ModuleWithHttp
:
@Injectable()
export default class {
constructor(private fetchApi: FetchApi) {}
}
Y quiero usarlo de la siguiente manera:
@Component({
selector: ''main'',
providers: [FetchApi]
})
export default class extends ModuleWithHttp {
onInit() {
this.fetchApi.call();
}
}
Entonces, extendiendo una súper clase que ya inyecta una dependencia, quiero tener acceso a ella en sus hijos.
Probé de muchas maneras diferentes, incluso teniendo la super-clase como componente:
@Component({
providers: [FetchApi]
})
export default class {
constructor(private fetchApi: FetchApi) {}
}
Pero aún así, this.fetchApi
es null
, incluso en súper clase.
Si desea evitar este código de "placa de la caldera", los servicios de inyección en clases secundarias solo se inyectan en el constructor de las clases primarias y luego se utilizan de forma efectiva los servicios en las clases secundarias a través de la herencia.
edit: de Angular 5.0.0 ReflectiveInjector ha sido desaprobado en favor de StaticInjector, a continuación se actualiza el código para reflejar este cambio
Tener un mapa de servicios con deps,
export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = {
''FetchApi'': {
provide: FetchApi,
deps: []
}
}
Tener un soporte de inyector,
import {Injector} from "@angular/core";
export class ServiceLocator {
static injector: Injector;
}
configurarlo en AppModule,
@NgModule(...)
export class AppModule {
constructor() {
ServiceLocator.injector = Injector.create(
Object.keys(services).map(key => ({
provide: services[key].provide,
useClass: services[key].provide,
deps: services[key].deps
}))
);
}
}
usar el inyector en la clase padre,
export class ParentClass {
protected fetchApi: FetchApi;
constructor() {
this.fetchApi = ServiceLocator.injector.get(FetchApi);
....
}
}
y extienda la clase principal para que no tenga que inyectar el servicio FetchApi
.
export class ChildClass extends ParentClass {
constructor() {
super();
...
}
onInit() {
this.fetchApi.call();
}
}
Tal vez una respuesta tardía, pero resolví inyectar solo el inyector en el BaseComponent y en todas las subclases, de esa manera no necesito mantener un localizador de servicios.
Mi clase base:
constructor(private injectorObj: Injector) {
this.store = <Store<AppState>>this.injectorObj.get(Store);
this.apiService = this.injectorObj.get(JsonApiService);
this.dialogService = this.injectorObj.get(DialogService);
this.viewContainerRef = this.injectorObj.get(ViewContainerRef);
this.router = this.injectorObj.get(Router);
this.translate = this.injectorObj.get(TranslateService);
this.globalConstantsService = this.injectorObj.get(GlobalConstantsService);
this.dialog = this.injectorObj.get(MatDialog);
this.activatedRoute = this.injectorObj.get(ActivatedRoute);
}
Mis clases de niños:
constructor( private injector: Injector) {
super(injector);
}
Tienes que inyectar fetchAPI en la súper clase y pasarlo a la clase infantil
export default class extends ModuleWithHttp {
constructor(fetchApi: FetchApi) {
super(fetchApi);
}
onInit() {
this.fetchApi.call();
}
}
Esta es una característica de cómo funciona la DI en general. La súper clase creará una instancia del niño a través de la herencia, pero debe proporcionar los parámetros necesarios para el niño.