0
votes

I have a chart here with a line and area graph here.

enter image description here

Then I have a chart here with just the line rendered, and a button to add the area graph data.

enter image description here

In the 2nd plnkr example, when you click the Add 2nd Chart button, I add data2 into data and then call drawChart again. However the chart doesn't draw and I see a ton of Invalid value for <path> errors.

In the console, I see that my data array gets the 2 objects, so I'm not sure where it's going wrong. Thoughts?

var data = [{
    "key": "Price",
    "type": "line",
    "yAxis": 2,
    "values": [
      [1443621600000, 71.89],
      [1443619800000, 75.51],
      [1443618000000, 12.49],
      [1443616200000, 20.72],
      [1443612600000, 70.39],
      [1443610800000, 59.77],
    ]
  }];

  var data2 = [{
    "key": "Quantity1",
    "type": "area",
    "yAxis": 1,
    "values": [
      [1136005200000, 1],
      [1138683600000, 5],
      [1141102800000, 10],
      [1143781200000, 0],
      [1146369600000, 1],
      [1149048000000, 0],
    ]
  }];

  // Draw initial chart:
  drawChart(data);

  function drawChart(data, option) {

    // Clear out old chart:
    // d3.selectAll("svg > *").remove();
    // data  = [];
    // chart = {};

    console.log('data',data);

    data = data.map(function(series) {
      series.values = series.values.map(function(d) {
        return {
          x: d[0],
          y: d[1]
        }
      });
      return series;
    });

    console.log('data after map function:',data);

    if (option) {
      console.log('2nd data object added:');
      data2 = data2.map(function(series) {
        series.values = series.values.map(function(d) {
          return {
            x: d[0],
            y: d[1]
          }
        });
        return series;
      });
      data.push(data2[0]);
      console.log('data',data);
    }

  nv.addGraph(function() {
    chart = nv.models.multiChart()
      .margin({
        top: 20,
        right: 40,
        bottom: 50,
        left: 40
      })
      .yDomain1([0, 10])
      .yDomain2([0, 100]) // hard-coded :<
      .interpolate("linear") // don't smooth out the lines
      .color(d3.scale.category10().range());

    chart.xAxis.tickFormat(function(d) {
      return d3.time.format('%I:%M')(new Date(d));
    });
    chart.yAxis1.tickFormat(d3.format(',f'));
    chart.yAxis2.tickFormat(function(d) {
      return '$' + d3.format(',f')(d)
    });

    d3.select('svg#chart')
      .datum(data)
      .transition().duration(500).call(chart);

    chart.tooltip.hidden(true);

    chart.update();

    d3.selection.prototype.moveToFront = function() {
        return this.each(function() {
            this.parentNode.appendChild(this);
        });
    };

    d3.selection.prototype.moveToBack = function() { 
        return this.each(function() { 
            var firstChild = this.parentNode.firstChild; 
            if (firstChild) { 
                this.parentNode.insertBefore(this, firstChild); 
            } 
        }); 
    };

    // d3.select('svg#chart .lines1wrap').moveToFront();
    d3.select('svg#chart .lines2wrap').moveToFront();
    d3.select('svg#chart .nv-areaWrap').moveToBack();
    d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());

    // Add top padding to xAxis timeline:
    d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > g > g.tick > text').each(function(d,i) {
        d3.select(this).attr('dy', '1.5em');
    });

    d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > .nv-axisMaxMin > text').each(function(d,i) {
        d3.select(this).attr('dy', '1.5em');
    });

    nv.utils.windowResize(chart.update);

    return chart;
  });
}

function toggle2nd() {
  vm.multiChart = !vm.multiChart;

  if (vm.multiChart) {
    console.log('clicked add 2nd button:',data)
    drawChart(data, true);
  }
}

Update, I moved the data.map function into the drawChart function as per Molda. However when I click the Add Chart button to redraw the chart with 2 graphs, for some reason both the x and y values for the values array for data become undefined. So now after clicking the button, the orange area graph gets charted, but I lose the line graph. Still get the Invalid value errors, but probably due to the undefined x and y.

http://plnkr.co/edit/2pFDDITuPc7XaL0eR4AA?p=preview

enter image description here

2
Well you didn't do what I suggested you moved data=data.map... You should have changed that to res=res.map.... So remove both data=data.map... and data2=data2.map... and use res=res.data... inside drawChart functionMolda
I meant res=res.map not res.dataMolda
well I changed res to data function drawChart(data, option) { so it should have worked. Did you try this in plnkr?Leon Gaban
I'm just adding in the x and y manually now, the map function just stops working when the 2nd data array is added.Leon Gaban

2 Answers

0
votes

You are mapping data.values to x,y before you call drawChart the first time. Do the same before you call drawChart again.

Update Change this

data = data.map(function(series) {         
  series.values = series.values.map(function(d) {             
        return { x: d[0], y: d[1] }
     });          
     return series; 
});     

function drawChart(res) { 

to this

function drawChart(res) { 

res = res.map(function(series) { 
      series.values = series.values.map(function(d) { 
             return { x: d[0], y: d[1] }
       }); 
       return series; 
}); 

Another update

Working code, see added lines

plnkr here

var data1 = [{
            "key": "Pricexcv",
            "type": "line",
            "yAxis": 2,
            "values": [
              [1443621600000, 71.89],
              [1443619800000, 75.51],
              [1443618000000, 12.49],
              [1443616200000, 20.72],
              [1443612600000, 70.39],
              [1443610800000, 59.77]
            ]
          }];

          var data2 = {
            "key": "Quantity1",
            "type": "area",
            "yAxis": 1,
            "values": [
              [1136005200000, 1],
              [1138683600000, 5],
              [1141102800000, 10],
              [1143781200000, 0],
              [1146369600000, 1],
              [1149048000000, 0]
            ]
          };


          drawChart(data1);

          function drawChart(res, option) {

            // Clear out old chart:
            // d3.selectAll("svg > *").remove();
            // data  = [];
            // chart = {};

            console.log('data',res);



          nv.addGraph(function() {
            chart = nv.models.multiChart()
              .margin({
                top: 20,
                right: 40,
                bottom: 50,
                left: 40
              })

/// these two lines added----------------------
              .x(function(d) { return d[0] })
              .y(function(d) { return d[1] })
/// these two lines added----------------------


              .yDomain1([0, 10])
              .yDomain2([0, 100]) // hard-coded :<
              .interpolate("linear") // don't smooth out the lines
              .color(d3.scale.category10().range());

            chart.xAxis.tickFormat(function(d) {
              return d3.time.format('%I:%M')(new Date(d));
            });
            chart.yAxis1.tickFormat(d3.format(',f'));
            chart.yAxis2.tickFormat(function(d) {
              return '$' + d3.format(',f')(d)
            });

            d3.select('svg#chart')
              .datum(res)
              .transition().duration(500).call(chart);

            chart.tooltip.hidden(true);

            chart.update();

            d3.selection.prototype.moveToFront = function() {
                return this.each(function() {
                    this.parentNode.appendChild(this);
                });
            };

            d3.selection.prototype.moveToBack = function() { 
                return this.each(function() { 
                    var firstChild = this.parentNode.firstChild; 
                    if (firstChild) { 
                        this.parentNode.insertBefore(this, firstChild); 
                    } 
                }); 
            };

            // d3.select('svg#chart .lines1wrap').moveToFront();
            d3.select('svg#chart .lines2wrap').moveToFront();
            d3.select('svg#chart .nv-areaWrap').moveToBack();
            d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());

            // Add top padding to xAxis timeline:
            d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > g > g.tick > text').each(function(d,i) {
                d3.select(this).attr('dy', '1.5em');
            });

            d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > .nv-axisMaxMin > text').each(function(d,i) {
                d3.select(this).attr('dy', '1.5em');
            });

            nv.utils.windowResize(chart.update);

            return chart;

          });
        }

        $scope.toggle2nd = function() {
            data1.push(data2);
            drawChart(data1);
        }
0
votes

I removed the need for the map function(different bug)

Then to add in a 2nd chart into the data Array, I updated the toggle2nd() function like so:

function toggle2nd() {
    vm.multiChart = !vm.multiChart;

    if (vm.multiChart) {
        data.push(data2[0]);
        drawChart(data);
    }
}

Full code:

var data = [{
    "key": "Price",
    "type": "line",
    "yAxis": 2,
    "values": [
      { x: 1443621600000, y: 71.89 },
      { x: 1443619800000, y: 75.51 },
      { x: 1443618000000, y: 12.49 },
      { x: 1443616200000, y: 20.72 },
      { x: 1443612600000, y: 70.39 },
      { x: 1443610800000, y: 59.77 }
    ]
  }];

  var data2 = [{
    "key": "Quantity1",
    "type": "area",
    "yAxis": 1,
    "values": [
      { x: 1136005200000, y: 1 },
      { x: 1138683600000, y: 5 },
      { x: 1141102800000, y: 10 },
      { x: 1143781200000, y: 0 },
      { x: 1146369600000, y: 1 },
      { x: 1149048000000, y: 0 }
    ]
  }];

  // Draw initial chart:
  drawChart(data);

  function drawChart(res) {
    console.log('res',res);

    nv.addGraph(function() {
      chart = nv.models.multiChart()
        .margin({
          top: 20,
          right: 40,
          bottom: 50,
          left: 40
        })
        .yDomain1([0, 10])
        .yDomain2([0, 100]) // hard-coded :<
        .interpolate("linear") // don't smooth out the lines
        .color(d3.scale.category10().range());

      chart.xAxis.tickFormat(function(d) {
        return d3.time.format('%I:%M')(new Date(d));
      });
      chart.yAxis1.tickFormat(d3.format(',f'));
      chart.yAxis2.tickFormat(function(d) {
        return '$' + d3.format(',f')(d)
      });

      d3.select('svg#chart')
        .datum(res)
        .transition().duration(500).call(chart);

      chart.tooltip.hidden(true);

      chart.update();

      d3.selection.prototype.moveToFront = function() {
          return this.each(function() {
              this.parentNode.appendChild(this);
          });
      };

      d3.selection.prototype.moveToBack = function() { 
          return this.each(function() { 
              var firstChild = this.parentNode.firstChild; 
              if (firstChild) { 
                  this.parentNode.insertBefore(this, firstChild); 
              } 
          }); 
      };

      // d3.select('svg#chart .lines1wrap').moveToFront();
      d3.select('svg#chart .lines2wrap').moveToFront();
      d3.select('svg#chart .nv-areaWrap').moveToBack();
      d3.select('.lines2Wrap').node().parentNode.insertBefore(d3.select('.stack1Wrap').node(), d3.select('.lines2Wrap').node());

      // Add top padding to xAxis timeline:
      d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > g > g.tick > text').each(function(d,i) {
          d3.select(this).attr('dy', '1.5em');
      });

      d3.selectAll('.nv-x.nv-axis > .nv-wrap.nv-axis > .nv-axisMaxMin > text').each(function(d,i) {
          d3.select(this).attr('dy', '1.5em');
      });

      nv.utils.windowResize(chart.update);

      return chart;
    });
}

function toggle2nd() {
  vm.multiChart = !vm.multiChart;

  if (vm.multiChart) {
    data.push(data2[0]);

    drawChart(data);
  }
}