Search code examples
angulardependency-injectionangular-services

Using Angular Service with multiple internal dependencies in a model class


i have a model class, which takes one argument "id" in it's constructor, but the title are in a map in a different service. let's call it name service. i want to set the Item's title when it's new instance is being created. following approach won't work is Item is not an angular class.

export class Item {
  id: string;
  title: string;

  constructor(id: string, private nameService: NameService) {
    this.id = id;
    this.title = nameService.nameDictionary[id];
  }

}

I can pass the service instance in constructor but i don't what to do that as class Item is being used from many places and i don't want to pass NameService object from constructor.

NameService have several internal dependencies as well.

@Injectable({
  providedIn: 'root'
})
export class NameService {

  nameDictionary: any = {};

  constructor(private config, private lib: LibraryService, private util: UtilityService) {

  }
}

Can anyone please guide me how can i set the title field from NameService on Item Class instantiation? Thanks


Solution

  • You can save a reference to angular's root injector after bootstrapping the application, and access it in your class. Use it to access your nameService.

    Simple StackBlitz demo

    main.ts

    export var ApplicationInjector: Injector;
    
    platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
      ApplicationInjector = ref.injector;
    }).catch(err => console.error(err));
    

    item.ts

    import { ApplicationInjector } from '../../main' // or some other path to main.ts file
    
    export class Item {
      id: string;
      title: string;
    
      constructor(id: string) {
        this.id = id;
        if (ApplicationInjector) {
          let nameService: NameService = ApplicationInjector.get(NameService);
          this.name = nameService.title;
        }
      }
    }
    

    NOTE: if the ApplicationInjector is undefined it is because that this class initialized before the module as finished to initialize. fixing this would be to wrap this code in a setTimeout.

    setTimeout(() => {
      if (ApplicationInjector) {
        let nameService: NameService = ApplicationInjector.get(NameService);
        this.name = nameService.title;
      }
    }, 0);