javascript - D3 chart indside bootstrap tab -
i'm tryng implement d3 chart angular 4 ,every thing works fine ,now i'm tryng put svg element inside bootstrap tab error.
error error: uncaught (in promise): typeerror: cannot read property 'nativeelement' of undefined
html code
<ul class="nav nav-tabs profile-tab" role="tablist"> <li class="nav-item"> <a class="nav-link active" data-toggle="tab" href="#profile" role="tab">profile</a> </li> </ul> <div class="tab-content"> <div class="tab-pane active" id="profile" role="tabpanel"> <div class="card-block"> <svg width="560" height="400"></svg> </div> </div> </div> the angular code lines caused problem
mycomponent code
import { component, oninit, ondestroy,afterviewinit, viewchild , elementref} '@angular/core'; import * d3 'd3'; @component({ selector: 'jhi-pathway-detail', templateurl: './pathway-detail.component.html' }) export class pathwaydetailcomponent implements oninit, ondestroy, afterviewinit { @viewchild('svg') svgelement: elementref; svg= this.svgelement.nativeelement; color; simulation; link; node; constructor( ) { } ngoninit() { } ngafterviewinit(){ this.svg = d3.select("svg"); let width = this.svg.attr("width"); let height =this.svg.attr("height"); this.color = d3.scaleordinal(d3.schemecategory20); this.simulation = d3.forcesimulation() .force("link", d3.forcelink().id(function(d) { return d.id; })) .force("charge", d3.forcemanybody()) .force("center", d3.forcecenter(width / 2, height / 2)); this.render(this.grapgdata); } ticked() { this.link .attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); this.node .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); } render(graph){ this.link = this.svg.append("g") .attr("class", "links") .selectall("line") .data(graph.links) .enter().append("line") .attr("stroke-width", function(d) { return math.sqrt(d.value); }); this.node = this.svg.append("g") .attr("class", "nodes") .selectall("circle") .data(graph.nodes) .enter().append("circle") .attr("r", 5) .attr("fill", (d)=> { return this.color(d.group); }) .call(d3.drag() .on("start", (d)=>{return this.dragstarted(d)}) .on("drag", (d)=>{return this.dragged(d)}) .on("end", (d)=>{return this.dragended(d)})); this.node.append("title") .text(function(d) { return d.id; }); this.simulation .nodes(graph.nodes) .on("tick", ()=>{return this.ticked()}); this.simulation.force("link") .links(graph.links); } dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } dragended(d) { if (!d3.event.active) this.simulation.alphatarget(0); d.fx = null; d.fy = null; } dragstarted(d) { if (!d3.event.active) this.simulation.alphatarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } }
you need use elementref directly reference dom elements. in template, this:
<svg width="560" height="400" #svg></svg> in class, create instance variable:
import { ..., viewchild, elementref } '@angular/core'; ... @viewchild('svg') svgelement: elementref; ... drawsvg() { let svg = this.svgelement.nativeelement; let width = svg.attr("width"); let height = svg.attr("height"); ... }
Comments
Post a Comment