Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add providers to Injector dynamically?

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

Is there a way to specify providers dynamically from, say, constructor of the component?

like image 427
Kugel Avatar asked Jan 10 '16 23:01

Kugel


People also ask

Which provider is used for dynamic Dependency Injection?

Factory providers: useFactory link The useFactory provider key lets you create a dependency object by calling a factory function, as in the following example. The injector provides the dependency value by invoking a factory function, that you provide as the value of the useFactory key.

What is a provider in Dependency Injection?

A dependency provider configures an injector with a DI token, which that injector uses to provide the concrete, runtime version of a dependency value. The injector relies on the provider configuration to create instances of the dependencies that it injects into components, directives, pipes, and other services.

What is providers in App Module TS?

A provider is an instruction to the Dependency Injection system on how to obtain a value for a dependency. Most of the time, these dependencies are services that you create and provide.

What is true about the useClass provider option?

Class Provider: useClassThe useClass expects us to provide a type. The Injector creates a new instance from the type and injects it. It is similar to calling the new operator and returning instance. If the type requires any constructor parameters, the injector will resolve that also.


2 Answers

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;
    }
}
like image 73
Hien Nguyen Avatar answered Oct 01 '22 15:10

Hien Nguyen


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");
    }
}
like image 20
Shivprasad Koirala Avatar answered Oct 01 '22 16:10

Shivprasad Koirala