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

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

dependency injection - Angular How to inject an @Injectable programatically in a function

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...