Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force multiple components to use the same instance of a Service

The Context

I'm writing an Angular2 application, in which I want multiple services to be used to hit different endpoints. I would like for each service to cache its data in order to reduce the number of requests made, and also to allow multiple components to modify data in the cache before sending it to the endpoints.

The Code

@Injectable()
  export class MyService {

  private items: any;

  constructor (private http: Http) {
    this.items = [];
  }

  getItems () {
    if(!this.items) {
      return this.http.get(this.endpoint).map((data) => {
        this.items = data;
        return data;
      });
    } else {
      return Observable.of(this.items);
    }
  }

  addItem (item) {
    this.items.push(item);
  }

  saveItems () {
    return this.http.put(endpoint, this.items);
  }
}

Then Component1 might do:

userClickedAddItem (item) {
  this.myService.addItem(item);
}

And Component2 might do:

userClickedSave () {
  this.myService.saveItems().subscribe((items) => {
    // Do something
  });
}

Then in the components' modules I'm doing something like

@NgModule({
  providers: [MyService],
  declarations: [
    Component1
    Component2
  ]
})

The Problem

Since Angular2 instantiates individual instances of services provided, even though Component1 called addItem, Component2 thinks no items have been added, since it has a different instance of MyService. The Internet says that the way to handle this is by making services singletons by declaring them on the Application level. But I'd rather not do that, as I'm using a modular design for my application which is designed to lazy load modules only as they're needed; thus, I'd prefer to keep services organized according to the modules and components which will need to use them.

Angular2's page on Hierarchical Dependency Injection explains how to solve the opposite problem, when you want instances of services that have different data cached. But it doesn't explain how to accomplish what I want, which is to have that data persisted between different components which use the same service. The explanation it gives also makes me think that providing the service on the module level should be enough, yet I'm still getting separate instances of the service in my two components.

Is there a way to persist data in a service that's shared between two components, without raising the service's provider to the application module?

like image 808
A. Duff Avatar asked Jan 25 '17 00:01

A. Duff


1 Answers

According to Angular 2 documentation, what you want to achieve is possible between Parent and Child Components.

You declare the service in parent providers, then the children use the same instance.

If you declare it in AppModule, parent and child will use a different instance of the service.

More info Parent and children communicate via a service

like image 165
mickdev Avatar answered Oct 27 '22 10:10

mickdev