How to add providers to Injector dynamically?
Solution 1
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;
}
}
Solution 2
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");
}
}
Solution 3
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.
Related videos on Youtube
Comments
-
Kugel almost 2 years
Each component can specify new
Provider
s using itsproviders
property inComponentMetadata
.Is there a way to specify providers dynamically from, say,
constructor
of the component? -
amay0048 over 7 yearsThis doesn't seem to work now that 2.0.0 is released. I've been up against it trying to get this working.
-
Kugel over 6 yearsThis is not dynamic provider this is just delayed injection using Injector.
-
Shivprasad Koirala over 6 yearsYou mean you want to change the injector from within the component in some event click or some other place.
-
Kugel over 6 yearsyeah, say you have an user input and you want to use that input to set up a provider so that it's available to components instantiated later.
-
Andre Elrico almost 5 yearsAll of the dependencies resolved are in the scope of mainModule. OP asks to add dependencies on a component level.
-
Jeyabalan Thavamani over 2 yearsIs it possible inject useValue dynamically based on the condition looks like settingService.getLanguage() as you used.