1
votes

I'm trying to dynamically create different types of nvd3 charts in one svg element (mainly because I want to switch chart types on the fly). To do this, everytime I change the chart type I delete every child of my svg-Element and add the new chart.

This is all working great, the problem comes when the I am resizing my window and calling chart.update through nv.utils.windowResize. For some strange reason, during this process, the old charts gets added to the DOM again, and 2 charts are displayed.

Here's a picture of the effect: enter image description here

Here is an example plunker with the behaviour: Plunker. Simply click the button to change the chart type from line to bar, and resize the preview window, should do the trick.

Anyone had this problem before or knows anything I can try to solve this behaviour?

Thank you very much for any help!

2
It's probably a closure issue where the variable chart is left over from the last time. Have you tried doing nv.utils.windowResize(this.chart.update); It would help if you posted a full jsFiddle showing the issue. Hard to tell what's going on without seeing the other instances where you add charts. - jeznag
@jeznag Updated my question with a plunker link! Thank you :) - Michael Faisst
Were you ever able to solve this one? - Gabe Gates

2 Answers

0
votes

It looks to me like there's an issue with the way you're declaring chart. The let operator uses block scoping so your original code:

 if(that.useLine) {
   let chart = nv.models.lineChart();
 } else {
   let chart = nv.models.discreteBarChart();
 }

won't work. chart will only be defined within the if block. You can do this instead (note that chart is declared outside the closure):

private addGraph(): void {

  let that = this;
  let chart;

  nv.addGraph(() {

    d3.selectAll(`svg > *`).remove();

    if(that.useLine) {
      chart = nv.models.lineChart();
    } else {
      chart = nv.models.discreteBarChart();
    }

    let myData = that.testData();

    d3.select('#chart svg')   
      .datum(myData) 
      .call(chart);

    //Update the chart when window resizes.
    nv.utils.windowResize(function() { chart.update() });
    return chart;
  });
}

https://plnkr.co/edit/pwiO8FCpGyd2JLG4hllW?p=preview

0
votes

I was able to get around this by passing a custom callback function into the nv.utils.windowResize method. When resizing the chart appears to strobe since it's deleting and rebuilding so many times, but I could not figure out an alternative way to accomplish this.

    var removeChart = function(element) {
        d3.select(element).selectAll('*').remove();
        d3.selectAll('.nvtooltip').style('opacity', '0');
    };

    nv.utils.windowResize(function() {
        // chartElement is a reference to the chart's <svg> element
        removeChart(chartElement);
        chart.update();
    });