2

My App has a Header section and body section, I am using routes so that the body section can navigate between pages, while the header is always there.

The data for the header comes from two services productService.getProducts() and priceService.getPrices() which is able to be modified on two of the pages productService.addProduct(produceID), productService.removeProduct(productID).

The data in the services is updating correctly, but I need a way to tell the header to call getProducts() and getPrices() again.

I thought I could have a callback from the pages, but it seems you cannot include a callback in a route?

Pengyy
  • 37,383
  • 15
  • 83
  • 73
Michael
  • 1,087
  • 1
  • 9
  • 12
  • You might need to fire an event when the data gets updated in the service, so that header could listen (subscribe) when that happens. – Nugu Aug 17 '17 at 03:09
  • I agree with @Nugu are you using/understand observable(s)? It seems like a solid use case for a state tree using redux, if you don't already have one. Look into the Redux pattern. – Chris Aug 17 '17 at 03:11
  • possibly a duplicate of https://stackoverflow.com/a/45668262/2708210 – Rahul Singh Aug 17 '17 at 06:20

2 Answers2

4

You can define a Subject in your service and subscribe to it in your header's component. Every time you update data in service, just call Subject.next().

subject: Subject<string> = new Subject();

updateData() {
  // your own logic
  this.subject.next();
}

Then you can do what you want(such as call some other functions) at Subject.subscribe().

product$ = this.service.subject;   // Subject defined at your service

constructor() {
  this.product$.subscribe(() => {
    console.log('product data has been updated!');
  });
}

Also, If you just want to get the newest data, you can just transform updated data via subject.next(newestData), and then you can get what you want at subject.subscribe().

refer this simple Plunker demo.

Pengyy
  • 37,383
  • 15
  • 83
  • 73
  • Adding to this excellent answer, remmeber to `unsubscribe` your subject when view is destroyed. – FAISAL Aug 17 '17 at 06:56
  • @Faisal thanks for notation about **unsubscribe**, this can prevent from memory leak problem. But it maybe unnecessary for OP's specific requirement for `Header` is always displayed. – Pengyy Aug 17 '17 at 07:12
2

I think in order to solve your problem more efficiently you need to consider of using ngrx this way you can subscribe for a store in your header and then on related action gets fired you can run do stuff in your header.

It might be looking something like

  1. Dispatch an action that mutate the store
    this.store.dispatch(new yourthing.SomeAction());

  2. Subscribe for a change: this.store.select(fromYourThing.getYourThing) .subscribe((thing) => { // do stuff }); });

For more details on ngrx check these links:

https://blog.angular.io/announcing-ngrx-4-87df0eaa2806
https://blog.nrwl.io/ngrx-patterns-and-techniques-f46126e2b1e5
https://blog.nrwl.io/using-ngrx-4-to-manage-state-in-angular-applications-64e7a1f84b7b

Also run this example-app locally so you can see how it all goes in action.

angularrocks.com
  • 26,767
  • 13
  • 87
  • 104