Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.1k views
Welcome To Ask or Share your Answers For Others

1 Answer

Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...