Renderer2 does not render SVG element while using d3 js - Angular 4

Viewed 2760

After going through the below link

Using D3.js with Angular 2

I understood that we should not be manipulating DOM directly. So I started exploring to use Renderer2 of angular 4.

So I started to write some code to add svg to DOM. Below are the snippets of my code.

HTML code

<div class="row">
 <div class="col-12">
   <div #myBarGraph id="host"></div>
 </div>
</div>

Component.ts

export class BarGraphComponent implements OnInit {
 host:any;
 svg:any;
 @ViewChild('myBarGraph') myBarGraph:ElementRef;

 constructor(private renderer:Renderer2) { }

 ngOnInit() {
  //some logic
 }

 // called on some drop down selection
 teamSelection(){
  //some logic
   this.host = this.mybarGraph.nativeElement;
   buildSVG();
 }

 buildSVG():void {
   this.svg = this.renderer.createElement('svg');
   this.renderer.setAttribute(this.svg,'width','600');
   this.renderer.setAttribute(this.svg,'height','400');
   this.renderer.setAttribute(this.svg,'background-color','blue');
   this.renderer.appendChild(this.host,this.svg); 
 }
}

The above code is able to add the svg element to the DOM. But to my surprise, it actually not displaying the svg element!.

I did refer to the following questions

  1. Angular2 Renderer: Svg rect is rendered but not showing in page
  2. Angular2 does not render SVG in runtime

But I couldn't find the proper answer so far.

Below is a screenshot of the problem problem

As you can see above, svg is present in DOM, but it is not displayed in web page. Any help would be much appreciated.

2 Answers

You have correctly added an svg element with a height and width to the view. But an svg element does not have a background-color attribute. You can think of it as the canvas on top of which you layer other elements that have shape and colour.

You need to add another element to this view to see anything. Remove the background-color attribute from the svg, then, as you have added the svg element to the view, you can use d3 to add, say, a rect to the view:

d3.select(this.svg)
  .append('rect')
  .attr('x', 0)
  .attr('y', 0)
  .attr('width', 600)
  .attr('height', 400)
  .attr('fill', 'blue');

alternatively, you could just do the following:

@Component({
  selector: 'bar-chart',
  template: `
    <div class='bar-chart' #barChart></div>
  `
})
export class BarChartComponent implements OnInit {

  @ViewChild('barChart')
  public chart: ElementRef;

  public svg: any;

  private width: number = 600;
  private height: number = 400;

  ngOnInit() {
    this.svg = d3.select(this.chart.nativeElement)
      .append('svg')
      .attr('width', this.width)
      .attr('height', this.height);

    this.svg
      .append('rect')
      .attr('x', 0)
      .attr('y', 0)
      .attr('width', this.width)
      .attr('height', this.height)
      .attr('fill', 'blue');
  }
}
Related