D3.js and Ionic 2: Elements not in DOM on second page view -
i have created simple ionic app testing integration of d3.js. can found here: https://github.com/wberger/ionic2-d3js-test
i did integration follows:
- create app side navigation , single page (
home.html
) - add
home.html
menu. - load d3.js in index.html:
<script src="https://d3js.org/d3.v4.min.js"></script>
- add
<div id="chart"></div>
home.html
- create chart in
ngafterviewinit()
inhome.ts
the home
template defined follows (source):
<ion-header> <ion-navbar> <button menutoggle> <ion-icon name="menu"></ion-icon> </button> <ion-title> ionic blank </ion-title> </ion-navbar> </ion-header> <ion-content padding> world oyster. <p> if lost, <a href="http://ionicframework.com/docs/v2">docs</a> guide. </p> <div id="chart"></div> <p>after</p> </ion-content>
the chart creation implemented follows (source):
ngafterviewinit() { this.createchart(); } createchart() { var chart = d3.select("#chart").append("svg") .attr("width", 100) .attr("height", 100) .append("g"); var rows = [ {x: 1, y: 1}, {x: 2, y: 2}, {x: 3, y: 3}, ]; var xscale = d3.scalelinear() .range([0, 100]) .domain([1, 3]); var yscale = d3.scalelinear() .range([100, 0]) .domain([1, 3]); chart.selectall(".dot") .data(rows) .enter().append("circle") .attr("class", "dot") .attr("cx", (row) => { return xscale(row.x) }) .attr("cy", (row) => { return yscale(row.y) }) .attr("r", 3.5); }
when starting app, chart displayed intended. when (re-)opening page side menu, chart not there. when inspecting ts/dom in google chrome, can observe following behaviour when re-opening:
ngafterviewinit()
gets called , in turn calls 'createchart()'- the created svg elements still there
- a second svg element created , filled
createchart()
after ngafterviewinit()
created svg gone. seems dom replaced empty (or cached??) template.
so questions are:
- what goes wrong here? should know?
- how can fix that?
i solved issue building chart component:
@component({ selector: 'my-chart', inputs: ['options', 'data'], template: `` }) export class mychart implements onchanges { el: any; options: mychartoptions; data: mychartdata; chart: any; arcmap: any; /** * initializes component root element. */ constructor(@inject(elementref) elementref: elementref) { this.el = elementref.nativeelement; } /** * handler binding changes. * @param changes changed bound values. */ ngonchanges(changes) { if (changes.options) { this.updatewithoptions(this.options); } if (changes.data) { this.updatewithdata(this.data); } } // handlers, drawing etc. ... }
it can integrated follows:
<my-chart [data]="chartdata" [options]="chartoptions"></my-chart>
don't forget register component in app.module.ts
, e.g.:
import { mychart } '../components/charts/my-chart'; // ... @ngmodule({ declarations: [ // ... mychart ], imports: [ // ... ], bootstrap: [myapp], entrycomponents: [ // ... ], providers: [ // ... ] })
Comments
Post a Comment