How to add providers to Injector dynamically?

后端 未结 4 1081
北海茫月
北海茫月 2021-01-01 20:42

Each component can specify new Providers using its providers property in ComponentMetadata.

Is there a way to specify provider

相关标签:
4条回答
  • 2021-01-01 21:31

    I've done it in the bootstrap part.

    bootstrap(AppComponent,[
        provide( RequestOptions, { useClass: DefaultRequestOptions } ),
        provide(Http, { useFactory:
            function(backend, defaultOptions) {
                return new Http(backend, defaultOptions); },
            deps: [XHRBackend, RequestOptions]}),
    ]);
    

    I'm guessing it can be done in a component too:

    https://angular.io/docs/ts/latest/api/http/Http-class.html

    You make it dynamic by adding decisions into the factory function instead of just returning the same object.

    0 讨论(0)
  • 2021-01-01 21:31

    I used useFactory to determine what class will be used for provide. I share for whom concern.

    In component ts

    @Component({
        selector: 'app-chart',
        templateUrl: './chart.component.html',
        styleUrls: ['./chart.component.scss'],
        providers: [
            { provide: DateTimeAdapter, useClass: MomentDateTimeAdapter },
            { provide: OWL_DATE_TIME_FORMATS, useValue: CUSTOM_FORMATS },
            { provide: OwlDateTimeIntl, deps: [SettingService],
                useFactory: (settingsService) => settingsService.getLanguage()
            }
        ]
    })
    

    In service ts get class instance

    @Injectable()
    export class SettingService {
        public getLanguage(){
           return this.translate.currentLang == "ko" ? new KoreanIntl() : new DefaultIntl;
        }
    }
    
    0 讨论(0)
  • 2021-01-01 21:36

    Below are 3 broader steps you need to follow to implement dynamic providers. Please note i have commented many part of the code so that we focus on the main answer. If you want to see detailed step refer this Angular tutorial

    Step 1 :- Create the collection of the providers

    Create the collection and you can use the push method to add DI objects dynamically.

    var providerscoll:any = [];
    providerscoll.push({ provide: "1", useClass: DialogLogger });
    providerscoll.push({ provide: "2", useClass: ConsoleLogger });
    

    Step 2 :- Provide the providers collection in "NgModule" .

    Please see the Square bracket syntax.

    @NgModule({
        // code removed for clarity
        providers: [providerscoll]
    })
    export class MainModuleLibrary { }
    

    Step 3 :- Get the Injector object in constructor

    Get injector object in the constructor using DI and you can then look up using the "Get" method and the token. So if you provide "1" then you get something and if you provide "2" you get something.

    // code removed for clarity
    import {  Injector } from '@angular/core';
    // code removed for clarity
    export class CustomerComponent {
    constructor(public injector: Injector){
            this.logger = this.injector.get("2");
        }
    }
    
    0 讨论(0)
  • 2021-01-01 21:40

    There is one way to create component using ViewContainerRef, where is allowed to pass injector so I guess this should be possible but it is limited to create components dynamically:

    Create Injector:

    static create(options: {providers: StaticProvider[], parent?: Injector, name?: string}): Injector;
    
    // @param injector The injector to use as the parent for the new component.
    
    abstract createComponent<C>(
        componentFactory: ComponentFactory<C>, index?: number, injector?: Injector,
        projectableNodes?: any[][], ngModule?: NgModuleRef<any>): ComponentRef<C>;
    

    Pseudo code:

    class FooComponent {
    
      constructor(
        private readonly injector: Injector,
        private readonly viewContainer: ViewContainerRef){
        const customInjector = this.injector.create({ providers: [FooService], parent: injector });
        this.viewContainer.createComponent(componentFactory, 0, customInjector );
        ...
      }
    }
    

    Or similarly use Portal from Angular CDK.

    0 讨论(0)
提交回复
热议问题