1

I have a view which contains a < svg > element inside < ng-template>

<div *ngIf="data == undefined; else elseBlock">
   Sorry no data!
</div>
<ng-template #elseBlock>
   <svg id="areachart" width="100%" height="210"></svg>
</ng-template>

Using d3, I am trying to read width(baseValue) of the svg element, but d3.select('#areachart') returns me null in the code:

export class DrawAreaChart implements AfterViewInit {

    private data;

    constructor(){}

    ngAfterViewInit() {
       this.chartService.getData().subscribe(
           (result) => {
               if (result) {
                  this.data = result;

                  var svg = d3.select("#areachart"),
                  width = +svg.property("width").baseVal.value, /* The code fails here */
                  height = +svg.property("height").baseVal.value;

                  ....
                  ....
               }
           }
       );
    }
    ....
    ....
    ....
}

It throws error saying-

Cannot read property 'width' of null

Please help.

1 Answers1

2

data is initially null, but after this.data = result Angular has not had time to adjust the DOM before d3 tries to select (so effectively svg is still not in the frame).

You can run the d3 code on ngOnChanges

ngOnChanges(changes: SimpleChanges) {
  if(changes.data) {
    // d3 code here
  }
}

or perhaps use [hidden]="!data" on the svg div (although some caveats around this, see What is the equivalent of ngShow and ngHide in Angular2).

Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
  • Thanks for the explanation Richard. The `ngOnChanges` didn't worked for me, though I am able to do it with the hidden attribute. – Shivam Jaiswal Nov 30 '17 at 12:23