0

I have this custom class called SortState that represents sorting and paging on a table of records. Now I want to make that class talk to a service that displays a loading indicator. Apparently you can't use regular Angular dependency injection with classes, only with components. The answers I've found for working around this generally say to use something called ReflectiveInjector, which seems to have been replaced with Injector.

So I tried something like this:

export class SortState {
  private loader: LoadingService;

  constructor(state: Partial<SortState>) {
    const injector = Injector.create({providers: [{provide: LoadingService, deps: []}]});
    this.loader = injector.get(LoadingService);
    ...
  }
  ...
}

And it sort of seems to work, but I think it's creating its own instance of LoadingService, and I need it to use a singleton. So I figure maybe I need to use the providers array in the main AppModule, but I haven't been able to figure out the syntax to make that work.

1
  • You need to pass it an Injector when instantiating your SortState class. Commented May 21 at 0:09

2 Answers 2

0

Angular inject will work, but it should be used inside of injection context. I.e. class constructor should be called inside of injection context.

export class SortState {
  private loader = inject(LoadingService);

  constructor(state: Partial<SortState>) {
    ...
  }
  ...
}
//component
class MyDependantComponent {
// next line will be instantiated during comp instantiation
// inside of injection context already
  sortState = new SortState({...}); 

// OR
  injector = inject(Injector);
  someMethod() {
    const sortState = runInInjectionContext(this.injector, () => new SortState({...}));
    // doSomething

  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

I tried putting in private loader = inject(LoadingService); like you said. The IDE said inject wasn't defined, so I tried it with Inject instead. It didn't really work...when I tried console.log(this.loader) in the constructor, it said it was a function named ParamDecorator, not the LoadingService
it should be inject with a small. import { inject } from '@angular/core';
I tried that and I get this: RuntimeError: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext. That's even if I put this.loader = inject(LoadingService) inside the constructor. Are you saying that I have to run the constructor itself inside an injection context?
"Are you saying that I have to run the constructor itself inside an injection context?" That is exactly what I wrote in the answer
Alright just making sure
0

Make SortState a service, but provide it on component level. This way SortState is created for every component instance and can inject other services.

@Injectable() // empty instead of the common "providedIn: root"
export class SortState {
  private loader = inject(LoadingService); // should be fine now

  setInitialState(state: Partial<SortState>) { // not a constructor anymore
    ...
  }
  ...
}
@Component({
  providers: [SortState], // provide your SortState here
  ...
})
class MyDependantComponent {
  sortState = inject(SortState); // don't forget to set the initial (setInitialState)

Depending on your UseCase(s) you might want to think about migrating to a ngrx ComponentStore https://ngrx.io/guide/component-store?gad_source=1&gad_campaignid=22440788858&gbraid=0AAAAA_UZAyJHx15u2sO_2twCs1x9pHYsQ&gclid=EAIaIQobChMIir38-si0jQMVXp2DBx2vJR9hEAAYASAAEgISzfD_BwE

2 Comments

I'm not sure this will work for me; some of my components need multiple SortState instances.
@LukeBretscher that sounds like your component is too big. Cutting it in smaller parts and subcomponent can help you with that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.