Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to deal with OnChanges that requires an AfterViewInit

Tags:

angular

d3.js

I am using D3 with Angular2, following the example here. My component is like:

@Component({
selector: 'example-component',
template: '<div #someElement></div>'
})
class exampleComponent implements OnChanges, AfterViewInit {
  @ViewChild('someElement') someElement: any;
  @Input() someInput: any; //got from API in service provided by parent component

  htmlElement: any;
  selection: any;

  ngAfterViewInit() {
    this.htmlElement = this.someElement.nativeElement;
    this.selection = D3.select(this.htmlElement);
  }

  ngOnChanges() {
    if (!this.someInput) return;
    this.selection.append('svg');
// continue to build chart
  }
}

The problem with this is that the input can be ready before ngAfterViewInit is called. The if statement prevents the chart from being built before the input is ready but if it is ready before ngAfterViewInit then this.selection will be undefined when ngOnChanges is called. However one cannot add another condition for this.selection such as:

if (!this.someInput || !this.selection) return;

because then the chart will not be built at all in the case when the input is ready before ngAfterViewInit since ngOnChanges won't necessarily be called again after ngAfterViewInit.

Is there a best practice for a case like this? I realize that almost always the input will not be ready before ngAfterViewInit but it is possible. There are some similar concerns voiced here but it's not exactly the same.

Thanks in advance!

edit: after more experimentation it appears I can do

this.htmlElement = this.someElement.nativeElement;
this.selection = D3.select(this.htmlElement);

within ngOnChanges, even before ngAfterViewInit, which is surprising.

like image 249
d k Avatar asked Dec 01 '16 04:12

d k


1 Answers

There is a function on the SimpleChange object passed into ngChanges called isFirstChange which you can use to check if the change was before initialization (it will be true).

like image 63
JayChase Avatar answered Sep 27 '22 18:09

JayChase