-1

I have a chart configuration (with amCharts) in which an eventListener is registered for the bullets. This event listener triggers another function in my chart service.

I want to trigger a method in my component as soon as the eventListener in the chart service is triggered. How can I best solve this with Angular?

My service (chart.service.ts) looks like this:

getSingleChart(chart, amChart) {
  // some configs
  // ...

  this.chart.updateChart(amChart, () => {
    // some configs
    // ...
    amChart.addListener('clickGraphItem', this.bulletClicked);
  });

  // I don't know if this method is needed?
  // The idea here was to execute the method in the component, if the bulletClicked pro is true
  chartBulletClicked() {
    return this.bulletClicked = true;
  }
}

The method in my component that should be triggered (chart.component.ts):

onBulletClicked() {
    // ...
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Codehan25
  • 2,704
  • 10
  • 47
  • 94
  • Have you looked at https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service ? –  Oct 26 '20 at 11:53
  • Yes, I have, but I don't have a click handler in my component to trigger the function in the service. Somehow I don't get it right now ... – Codehan25 Oct 26 '20 at 12:00
  • 1
    You can subscribe to observables in your services that emit values to your component(s), similiar to how you'd do it with api calls –  Oct 26 '20 at 12:03
  • Thank you very much, with your hint I found the right solution. – Codehan25 Oct 26 '20 at 13:10

2 Answers2

1

You can define a subject in your service that will emit every times your eventListener get triggered and subscribe to this subject in your component and call your method on each new emission:

your service:


private _chartEventTriggered$: Subject<void> = new Subject();

get chartEventTriggered$(): Observable<void> {
    return this._chartEventTriggered$.asObservable();
}

getSingleChart(chart, amChart) {
  // some configs
  // ...

  this.chart.updateChart(amChart, () => {
    // some configs
    // ...
    amChart.addListener('clickGraphItem', () => this._chartEventTriggered$.next());
  });

}

in your component:

...
ngOnInit() {
    this.service.chartEventTriggered$.subscribe(() => this.onBulletClicked());
}

onBulletClicked() {
    // do stuff
}
...
Quentin Fonck
  • 1,286
  • 9
  • 14
  • 1
    I solved it pretty similarly. I only subscribe in my constructor and not in ngOnInit (this is also how it is in the Angular documentation). In addition, I did not create a getter, but solved it as here: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service – Codehan25 Oct 26 '20 at 13:08
  • 1
    the end result is the same, it is the correct way to do this. – Quentin Fonck Oct 26 '20 at 13:11
1

You need to use observables:

Service:

 privatereadonly chartBulletClicked$$ = new Subject<void>();
 public readonly chartBulletClicked$ = this.chartBulletClicked$$.asObservable();


getSingleChart(chart, amChart) {
  // some configs
  // ...

  this.chart.updateChart(amChart, () => {
    // some configs
    // ...
    amChart.addListener('clickGraphItem', () => this.chartBulletClicked$$.next());
  });

  // I don't know if this method is needed?
  // The idea here was to execute the method in the component, if the bulletClicked pro is true
  chartBulletClicked() {
    return this.bulletClicked = true;
  }
}

Component:

  private subscriptions = new Subscription();
  ngOnInit(){
    this.subscriptions.add(
      this.myService.chartBulletClicked$.subscribe(() => {
        // Do what you need
      });
    );
  }

  ngOnDestroy() {
    this.subscriptions.unsubscribe();
  }

It is REALLY important that you unsubscribe when your component is destroyed, otherwise you will have memory leaks.

(I wrote this here directly maybe there is one or two typos there)

distante
  • 6,438
  • 6
  • 48
  • 90