9

I have a child component that contains complex input (some chart data). I am sending this chart data from the parent component through the @Input() decorator in Angular 5 after getting API response. So, I need to sync the chart according with the API response every time it gets changed on the parent component, hence, the OnChange Lifecyle. But unfortunately, I am not able to get this to work properly. I tried with setting a dummy input field with basic number type and increment it but in vain. Here's my implementation:

Child chart component:

export class ChartComponent implements OnInit, OnChanges {

  @Input() chartData;
  @Input() triggerChart;

  ngOnChanges(changes: SimpleChanges) {
    console.log(changes);
  }

}

Parent component html:

<app-chart [chartData]="chartData" [triggerChart]="triggerChartData"></app-chart>
<input [(ngModel)]="triggerChartData" type="hidden">

Parent component:

this.chartService.getChartData(params).subscribe(res => {
  this.chartData = res;
  this.triggerChartData++;
});

PS: The ngOnChanges as the title indicates only fires once when the component initializes with undefined values.

6
  • Are you sure that your ChartData is resolving in the Parent component? Commented Jan 15, 2018 at 14:17
  • Yes, I am able to log the API response to the console. However, I noticed that the triggerChartData doesn't increment. It logs NaN Commented Jan 15, 2018 at 14:21
  • Try logging out the Input properties to your DOM instead using handlebars. {{ chartData | json }} within the child component. Objects are tough on change detection, because an Input will only pass the object as Reference, meaning change detection won't detect changes beyond the initial reference to the object within the parent component being defined. Commented Jan 15, 2018 at 14:26
  • 1
    In terms of the triggerChartData++ rendering NaN, trying initializing the property with a Number value: triggerChartData: number = 0. Then using ++ should work. Commented Jan 15, 2018 at 14:30
  • 1
    Read this stackoverflow.com/questions/38571812/… - Especially the edit "EDIT 2017-07-25:..." Commented Jan 15, 2018 at 14:32

2 Answers 2

13

Thanks to @HoangDucNguyen, here's the working code:

this.chartService.getChartData(params).subscribe(res => {
  this.chartData = res;
  this.changeDetectorRef.detectChanges();
});

Of course you will need to import the ChangeDetectorRef class from @angular/core and inject it in your constructor.

Explanation:
When variables are changed outside of the angular context (in here: it's the rxJs context), Angular isn't able to detect changes on the variables. So, you need to manually fire the detect changes angular method.

Official doc: https://angular.io/api/core/ChangeDetectorRef

Sign up to request clarification or add additional context in comments.

2 Comments

Nice, very thoughtful you are :)
Wow!! After spending many hours, this resolved the issue!! Thanks :)
0

you must use changeDetectorRef

this.cd.markForCheck();
if (!this.cd['destroyed']) {
    this.cd.detectChanges();
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.