1

I have a library with a component that has a provider, like so-

@Component({
  selector: "lib-layer-list-widget",
  templateUrl: "./layer-list-widget.component.html",
  styleUrls: ["./layer-list-widget.component.css"],
  providers: [LayerListWidgetService],
})
export class LayerListWidgetComponent {}

This component is being rendered in my angular project and
that service has methods I want to use from a component in my project.

example:

import {
  LayerListWidgetService,
} from "my-lib";

@Component({
  selector: "app-example",
  templateUrl: "./app-example.component.html",
  styleUrls: [],
})
export class AppExampleComponent {
    constructor( private layerListWidgetService: LayerListWidgetService) {
         let elements = this.layerListWidgetService.getLayerListElements();
    }
}

Problem is- this is not working properly because the instance I refer to here is not the same as the one that was created as a provider to the component.
I tried to read the documentation and search around but I could not find a concrete answer.

Is there a way to access a component's provider (in a lib) from another component?

Shaked
  • 93
  • 1
  • 9
  • 1
    The question here is, is that component you need a service in an actual child of the component that has the service on component level? If so, you can manually get the injector service from Angular (injector.get('name')) - which *should* get the first injector it encounters from the injector tree (in this case the parent service). Just make sure you decorate it with @Optional (en check if it is there) - to prevent tight coupling. – MikeOne Jun 09 '21 at 14:41

1 Answers1

0

Remove the provider at the component level, and add it to the providers array at the NgModule level.

i.e.

    @NgModule({
       providers: [LayerListWidgetService]
    })

Components have their own injectors, which forms a hierarchy with other components in the same tree. But if you add the providers to the NgModule, it gets registered with the closest NgModule injector (which is either the lazy loaded module, or the root injector). Services which utilize the same injector (or hierarchical injector) can be shared between components which also use the same injector.

Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • I use a component's provider because I have several instances of the component and I want each of those to have its own service. – Shaked Jun 09 '21 at 11:07
  • Ah I understand. I would suggest having a root service that coordinates (or finds) and subscribes to child services. – Michael Kang Jun 09 '21 at 11:12
  • Do you have an example? How am I supposed to "find" this specific instance of the provider? – Shaked Jun 09 '21 at 11:34
  • I dont't understand this: "I use a component's provider because I have several instances of the component" - so how would you ever know which instance you need for that 'other' component? If what you need on the service is like a stateless helper function, just make it static and don't DI the service (just import). – MikeOne Jun 09 '21 at 11:41
  • @MikeOne your question is exactly my problem... my service is not a stateless helper function, it holds a large part of my component logic and its children's too - I cannot get rid of it... – Shaked Jun 09 '21 at 12:02
  • The parent component would have a service (scoped to the parent). You can inject the parent service into the child component, and start subscribing to events. In that way the parent service can subscribe to child events and the child service can subscribe to parent events - depending on how you want them to communicate. Its a way of allowing components to communicate through events. Usually you need a coordinator of the interaction - that is the role of the parent service. – Michael Kang Jun 09 '21 at 12:03