Search code examples
angulartypescriptdependency-injection

Angular providers: Use existing or create one if not provided


In Angular 2+, how can I provide a new instance of an Injectable only if there's no instance existing?

I searched and found none so I tried useFactory. This is my code so far:

{
  provide: ColorsService,
  useFactory: (colorService: ColorsService, colors: string[]) => {
    if (colorService) return colorService;
    return new ColorsService(colors);
  },
  deps: [ColorsService, MY_COLORS],
},

Besides the fact that I'm injecting the MY_COLORS token manually, I get a weird error:

Error: Circular dep for ColorsService


Solution

  • So with the help of @eko I found this solution:

    @Component({
      ...
      providers: [ColorsService],
    })
    export class ChildComponent {
      colorService: ColorsService;
      constructor(
        @Self() currentColorService: ColorsService,
        @Optional() @SkipSelf() parentColorService?: ColorsService,
      ) {
        this.colorService = parentColorService ?? currentColorService;
      }
    }
    

    In this example, the parentColorService is the service that might be provided by a parent component. If it's not provided, I'll use the currentColorSerivce which is instantiated in this component (it's instantiated anyway which may not be a good thing).