2015-11-28 42 views
15

Ho la seguente classe ModuleWithHttp:Come estendere un componente con Injection dipendenza in Angular 2?

@Injectable() 
export default class { 
    constructor(private fetchApi: FetchApi) {} 
} 

e voglio usarlo come segue:

@Component({ 
    selector: 'main', 
    providers: [FetchApi] 
}) 
export default class extends ModuleWithHttp { 
    onInit() { 
    this.fetchApi.call(); 
    } 
} 

così estendendo una classe super-che inietta già una dipendenza voglio avere un accesso a nei suoi bambini.

Ho provato molti modi diversi, pur avendo super-classe come un componente:

@Component({ 
    providers: [FetchApi] 
}) 
export default class { 
    constructor(private fetchApi: FetchApi) {} 
} 

Ma ancora, è this.fetchApinull, anche in super-class.

+0

che devono essere iniettate FetchApi nella classe che eredita, ma se ti aiuta, è possibile accedervi dalla classe base fare qualcosa come '( questo) .fetchapi.call (...)' (non è necessario passarlo esplicitamente tramite 'super()'. – rinogo

risposta

23

si deve iniettare fetchAPI nella classe super e tramandarlo alla classe bambino

export default class extends ModuleWithHttp { 

    constructor(fetchApi: FetchApi) { 
    super(fetchApi); 
    } 

    onInit() { 
    this.fetchApi.call(); 
    } 
} 

Questa è una caratteristica di come funziona DI in generale. La super classe istanzia il bambino tramite l'ereditarietà, ma devi fornire i parametri richiesti al bambino.

+0

Questo è quello che leggo anch'io.Volevo astrarre DI per evitare tutto questo testo, ma vedo che ho bisogno di importare, iniettare ed estendere sottoclassi quasi nello stesso modo. – squixy

+1

Non capisco questo. Per "classe base" intendi "classe derivata" (normalmente "classe base" sarebbe uguale a "superclasse")? Nel tuo esempio, "fetchAPI" è "passato"? Stai dicendo che se costruisco una nuova classe derivata verranno fatte le iniezioni richieste nella superclasse? –

+3

_ "Questa è una funzionalità di come DI funziona in generale" _ - in generale in modo angolare, ma non in generale ovunque. Molti framework supportano DI attraverso il binding delle proprietà. – Qwertiy

53

Se si vuole evitare questo codice "refusi" l'iniezione di servizi delle classi figlio solo per l'iniezione nel costruttore classi madri e poi in modo efficace utilizzando tale servizi delle classi dei bambini attraverso l'eredità, si potrebbe fare questo:

edit: da Angular 5.0.0 ReflectiveInjector è stato deprecato in favore di StaticInjector, di seguito viene aggiornato il codice per riflettere questa modifica

avere una mappa dei servizi con dipendenze,

export const services: {[key: string]: {provide: any, deps: any[], useClass?: any}} = { 
    'FetchApi': { 
    provide: FetchApi, 
    deps: [] 
    } 
} 

Avere un supporto dell'iniettore,

import {Injector} from "@angular/core"; 

export class ServiceLocator { 
    static injector: Injector; 
} 

impostare in 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 
     })) 
    ); 
    } 
} 

utilizzare l'iniettore in classe genitore,

export class ParentClass { 

    protected fetchApi: FetchApi; 

    constructor() { 
    this.fetchApi = ServiceLocator.injector.get(FetchApi); 
    .... 
    } 
} 

e si estendono classe madre in modo da non lo fai è necessario iniettare il servizio FetchApi.

export class ChildClass extends ParentClass { 
    constructor() { 
    super(); 
    ... 
    } 

    onInit() { 
    this.fetchApi.call(); 
    } 
} 
+0

Come posso iniettare un servizio da bambino e usarlo dal genitore? –

+0

Penso che non puoi e non ha senso per me. Qual è il tuo caso d'uso? –

+3

Sono con Petr - per quanto ne so, le classi genitore non sono affatto a conoscenza di nulla nelle loro sottoclassi. Sarebbe come il personaggio di Roy Scheider di Jaws che sa cosa succede a Michael Caine in Jaws: The Revenge. E insisto che questa è un'analogia perfetta. – SilithCrowe

3

risposta Forse in ritardo, ma avevo deciso di iniettare solo l'iniettore sulla BaseComponent e in tutte le sottoclassi, in questo modo non ho bisogno di mantenere un localizzatore di servizio.

La mia base Classe:

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); 
} 

mie classi figlie:

constructor(private injector: Injector) { 

    super(injector); 

} 
Problemi correlati