I am trying to inject a provider into a reducer function programatically, and it fails miserably. I have tried ad nauseam using Injector.create(...)
in various combinations as well as inject(DependencyClass)
, but get only NullInjectorError for missing LocaleId
or "inject() must be called from an injection context". Any advice most welcome.
The dependency and the client code sit in different modules.The dependency injects another angular resource by @Inject(InjectionToken).
Dependency (Provider)
The dependency I am trying to inject looks like this:
import {Inject, Injectable, LOCALE_ID} from '@angular/core';
import {DecimalPipe} from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class LocalizeUtil {
constructor(
@Inject(LOCALE_ID) private locale,
private decimalPipe: DecimalPipe
) { }
localize(...): string {
...
}
// business methods omitted
}
it is - together with its own dependency - declared as provider in the app module:
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
CoreModule,
RootStoreModule,
HomeModule,
StoreDevtoolsModule,
],
providers: [
LocalizeUtil,
DecimalPipe
],
bootstrap: [
AppComponent
]
})
export class AppModule { }
in the module of the client code:
@NgModule({
declarations: [
...
],
exports: [
...
],
imports: [
CommonModule,
ReactiveFormsModule,
HttpClientModule,
SharedModule,
],
providers: [
...
LocalizeUtil,
DecimalPipe,
...
]
})
export class ClientModule { }
and even in its own module:
@NgModule({
...
providers: [
DecimalPipe,
LocalizeUtil
]
})
export class SharedModule { }
Client Code
Using Injector create/ get in the client module like so:
import {Injector} from '@angular/core';
import {LocalizeUtil} from '@shared/utils/localize-util';
function localize(numerical: number): string {
const injector = Injector.create({
providers: [{provide: LocalizeUtil, deps:[LOCALE_ID]}]
});
let localizer: LocalizeUtil;
try {
localizer = injector.get(LocalizeUtil);
} catch (e) {
console.log(e);
}
return localizer.localize(numerical, 1, 2);
}
produces
NullInjectorError: R3InjectorError[LocalizeUtil -> InjectionToken LocaleId]: NullInjectorError: No provider for InjectionToken LocaleId! at NullInjector.get
Using inject()
in the client module like so:
import {inject} from '@angular/core';
import {LocalizeUtil} from '@shared/utils/localize-util';
function localize(numerical: number): string {
let localizer: LocalizeUtil;
try {
localizer = inject(LocalizeUtil);
} catch (e) {
console.log(e);
}
return localizer.localize(numerical, 1, 2);
}
produces:
Error: inject() must be called from an injection context at injectInjectorOnly
Edit
I could eventually avoid this problem by injecting the utility class into the effect class triggering this reducer, where normal injection works as usual. I don't really consider this particular utility a side effect, as it is not calling anything asynchronous. Still, it could look like a side effect to the occasional passer-by, so I like to think of moving it as an improvement. Question remains, why it was not possible to inject by call to inject()
or the Injector
.
question from:
https://stackoverflow.com/questions/65915912/angular-how-to-inject-an-injectable-programatically-in-a-function