Search code examples
angulartypescriptangular2-services

Sharing an Angular 2 service between child components who don't share the same parent component


Let's say I have an Angular 2 that is structured as follows:

enter image description here

In other words, there is a root parent component A that contains instances of two distinct children components B and C.

Now say I want to create a MyService class to be shared across each vertical column of children components. More specifically, I want to be able to inject MyService into component B and component C's constructors, with Angular creating two instances of the service overall (one for the first column of child components and another for the second column of child components).

One way to do this is to wrap each column of child components in a intermediate component P and then declare MyService as a provider in its @Component decorator using providers: [MyService]. This ensures that each instance of P (and therefore all of its children components as well) will receive their own instance of MyService:

enter image description here

However, I would like to avoid this solution because creating an intermediary wrapper component like this seems like a lot of extra boiler plate and it also requires restructuring how components are laid out in component A's template.

Is there an easy way to achieve this in Angular 2? Thanks!


Solution

  • Parent component that hosts the injector and MyService provider is the correct solution. This is how Angular 2 DI works. Even if there were a singleton service, MyServiceFactory that can create MyService class instances, how would it determine that B and C should receive a common MyService instance, considering that there are several Bs and Cs?

    Parent component is preferable, unless there are unresolvable layout issues. Otherwise it can be a directive with MyService provider,

    @Directive({
      selector: '[p]',
      providers: [MyService]
    })
    class P {}
    

    that results in transparent layout with

    <ng-container p>
      <b></b>
      <c></c>
    </ng-container>
    <ng-container p>
      <b></b>
      <c></c>
    </ng-container>