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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With