[Chartjs]-Chart JS, Choose different Y-axis for different datasets

2👍

Fist of all in your barChartData.datasets[] you are using id but you should use yAxisIDinstead. giving id there has no impact on the chart. here is the doc for that: http://www.chartjs.org/docs/latest/charts/line.html#dataset-properties

Now onto what you’re asking, you can add a click handler to the legend to toggle between axes on click, here is an example of that:

a fork codepen off of yours with new code: https://codepen.io/anon/pen/ooZMwG?editors=0010

set options.legend.onClick to this function:

function(e, legendItem) {
    var index = legendItem.datasetIndex;
    var ci = this.chart;

    var axisIds = []
    var yAxes = ci.options.scales.yAxes;
    for (var i = 0; i < yAxes.length; i++) { // loop over the registered yAxes
        yAxes[i].gridLines.color = "rgba(0,0,0,0.1)"; // reset all scale gridlines to default
        axisIds.push(yAxes[i].id) // get all yAxes ids
    }

    var meta = ci.getDatasetMeta(index);
    var currentAxisId = meta.yAxisID
    var currentAxisIdIndex = axisIds.indexOf(currentAxisId);
    var newAxisIdIndex;
    // basically get the next axis id in the array, if the last one, get the first (circular)
    if (currentAxisIdIndex == axisIds.length - 1) newAxisIdIndex = 0;
    else newAxisIdIndex = currentAxisIdIndex + 1;

    var newAxisId = axisIds[newAxisIdIndex];
    meta.yAxisID = newAxisId // set the new axis id to the next one in the array

    axis = ci.scales[newAxisId];
    axis.options.gridLines.color = "rgba(0,0,0,1)"; // change lines color of the new axes 
    ci.update(); // update chart
}

**UPDATE: **

based on your new codepen, here are a few things to help:

I have added a new update to my answer to add offfset to all Y Axes in the chart. Use that instead of what you have in the pen.

then update your changeLeftRightY to the following and make sure your legend HTML container has the id: legend

changeLeftRightY = function(e, index) {
            //console.log("-- " + data.datasets[index].yAxisID)
            var ci = e.view.ch;
            var axisIds = []
            var yAxes = ci.options.scales.yAxes;
            for (var i = 0; i < yAxes.length; i++) { // loop over the registered yAxes
                yAxes[i].gridLines.color = "rgba(0,0,0,0.1)"; // reset all scale gridlines to default
                axisIds.push(yAxes[i].id) // get all yAxes ids
            }
            var meta = ci.getDatasetMeta(index);
            var currentAxisId = meta.yAxisID
            var currentAxisIdIndex = axisIds.indexOf(currentAxisId);
            var newAxisIdIndex;
            // basically get the next axis id in the array, if the last one, get the first (circular)
            if (currentAxisIdIndex == axisIds.length - 1) newAxisIdIndex = 0;
            else newAxisIdIndex = currentAxisIdIndex + 1;

            var newAxisId = axisIds[newAxisIdIndex];
            meta.yAxisID = newAxisId // set the new axis id to the next one in the array

            axis = ci.scales[newAxisId];
            axis.options.gridLines.color = "rgba(0,0,0,1)"; // change lines color of the new axes
            document.getElementById('legend').innerHTML = ci.generateLegend();

            ci.update()
        }

Here is a codepen with the code result *I have made some changes to some of your code to make it easier to read.

If that codepen is changed or deleted, here is the full code

// set default no fill beneath the line
Chart.defaults.global.elements.line.fill = false;
// Define a plugin to provide data labels
Chart.pluginService.register({
    beforeUpdate: function(chart){
      console.log("beforeUpdate");
      // get custom defined offset
      var offset = chart.options.customOffset;
      // exisit gracefully if offset not defined or less than 0
      if(!offset || offset < 0) return;
      var yAxes = chart.options.scales.yAxes;
      for(var i=0; i<yAxes.length; i++){
        var axis = yAxes[i];
        var datasets = chart.data.datasets;
        var max = Number.MIN_VALUE;
        var min = Number.MAX_VALUE;
        var datasetsOnAxis = [];

        for(var j=0; j<datasets.length; j++){ // add datasets for this axes to datasetsOnAxis
          var dataset = datasets[j];
          var meta = chart.getDatasetMeta(j);
          if  (meta.yAxisID === axis.id) datasetsOnAxis.push(dataset); 
        }

        for(var k=0; k<datasetsOnAxis.length; k++){
          var dataset = datasetsOnAxis[k]
          var newMax = Math.max.apply(null, dataset.data);
          var newMin = Math.min.apply(null, dataset.data);
          max = newMax > max ? newMax : max;
          min = newMin > min ? min : newMin;
        }
        axis.ticks.max = max + offset;
        axis.ticks.min = min - offset;   
      }
    }
});

var barChartData = {
  labels: [1510332261000, 1510332473000, 1510332489000, 1510332726000, 1510332777000, 1510332778000, 1510332958000, 1510333050000, 1510333131000, 1510333389000, 1510333476000, 1510333493000, 1510333588000, 1510333604000, 1510333664000, 1510333668000, 1510333758000, 1510333801000, 1510333820000, 1510333821000, 1510333878000, 1510333928000],
  datasets: [{
    type: 'line',
    label: 'a (F)',
    yAxisID: "y-axis-0",
    backgroundColor: "rgba(217,83,79,0.75)",
    data: [70, 72, 73, 73, 75, 50, 50, 40, 40, 45, 70, 73, 70, 73, 73, 73, 74, 73, 73, 73]
  }, {
    type: 'line',
    label: 'b (V)',
    yAxisID: "y-axis-0",
    backgroundColor: "rgba(92,184,92,0.75)",
    data: [12.9, 17.9, 15.9, 17.9, 17.9, 17.9, 15.9, 17.9, 15.8, 17.8, 16.8, 17.8, 17.9, 17.9, 17.8, 17.8, 19.8, 17.9, 17.8, 20.8]
  }, {
    type: 'line',
    label: 'c (%)',
    yAxisID: "y-axis-0",
    backgroundColor: "rgba(51,51,51,0.5)",
    data: [30, 30, 50, 30, 20, 10, 30, 40, 30, 50, 30, 70, 30, 50, 30, 80, 90, 30, 30, 30]
  }, {
    type: 'line',
    label: 'd (AH)',
    yAxisID: "y-axis-1",
    backgroundColor: "rgba(151,187,205,0.5)",
    data: [10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6, 10.6]
  }]
};

var options = {
  title: {
      display: true,
      text: "Chart.js"
    },
  legendCallback: function (chart) {
                console.log('legendCallback');
                var legendHtml = [];
                legendHtml.push('<div id="legend">');
                for (var i = 0; i < chart.data.datasets.length; i++) {
                    var meta = ch.getDatasetMeta(i);
                    var yAxis = meta.yAxisID =='y-axis-0' ? "Left Axis" : "Right Axis"

                    if (chart.data.datasets[i].label) {
                        var datasetIndex = chart.legend.legendItems[i].datasetIndex
                        var color = chart.data.datasets[i].backgroundColor;
                        var label = chart.data.datasets[i].label;
                        legendHtml.push(
                          '<div class="lgnd-item-container">'+
                            '<input class="lgnd-ckeckbox" type="checkbox" checked '+
                                    'onclick="updateDataset(event, '+datasetIndex+')"/>'+
                            '<div class="lgnd-square" style="background-color:'+color+'"></div>'+
                            '<div class="lgnd-label">'+label+' '+yAxis+'</div>'+
                            '<input class="lgnd-btn" type="button" value="Change" onclick="changeLeftRightY(event,'+datasetIndex +')"></input>'+
                          '</div>');
                    }
                }
                legendHtml.push('</div>');

                return legendHtml.join("");
            },
            legend:{
              display:false
            },
            customOffset: 2,
            responsive: true,
            tooltips: {
                mode: 'label',
                position: 'nearest'
            },
  scales: {
      xAxes: [{
        stacked: true
      }],
      yAxes: [{
        position: "left",
        id: "y-axis-0",
      }, {
        position: "right",
        id: "y-axis-1",
      }]
    }

}

// Show/hide chart by click legend
updateDataset = function (e, datasetIndex) {
            var index = datasetIndex;
            var ci = e.view.ch;
            var meta = ci.getDatasetMeta(index);
            // See controller.isDatasetVisible comment
            meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
            // We hid a dataset ... rerender the chart
            ci.update();
        };

var ctx = document.getElementById("myChart");
// allocate and initialize a chart
window.ch = new Chart(ctx, {
  type: 'line',
  data: barChartData,
  options: options

});
document.getElementById("chartLegend").innerHTML = ch.generateLegend();

changeLeftRightY = function(e, index) {
            //console.log("-- " + data.datasets[index].yAxisID)
            var ci = e.view.ch;
            var axisIds = []
            var yAxes = ci.options.scales.yAxes;
            for (var i = 0; i < yAxes.length; i++) { // loop over the registered yAxes
                yAxes[i].gridLines.color = "rgba(0,0,0,0.1)"; // reset all scale gridlines to default
                axisIds.push(yAxes[i].id) // get all yAxes ids
            }
            var meta = ci.getDatasetMeta(index);
            var currentAxisId = meta.yAxisID
            var currentAxisIdIndex = axisIds.indexOf(currentAxisId);
            var newAxisIdIndex;
            // basically get the next axis id in the array, if the last one, get the first (circular)
            if (currentAxisIdIndex == axisIds.length - 1) newAxisIdIndex = 0;
            else newAxisIdIndex = currentAxisIdIndex + 1;

            var newAxisId = axisIds[newAxisIdIndex];
            meta.yAxisID = newAxisId // set the new axis id to the next one in the array

            axis = ci.scales[newAxisId];
            axis.options.gridLines.color = "rgba(0,0,0,1)"; // change lines color of the new axes
            document.getElementById('legend').innerHTML = ci.generateLegend();

            ci.update()
        }

CSS:

.myChartDiv {
  max-width: 600px;
  max-height: 400px;
}
.lgnd-square {
  float: left;
  height: 20px;
  width:20px;
  overflow:hidden; 
  margin: 5px;
}

.lgnd-ckeckbox{
  float:left;
  margin: 10px;
}
.lgnd-btn{
  float: left;
  margin: 5px;
}
.lgnd-item-container{
  width: 300px;
  height: 40px;
}
.lgnd-label{
  float:left;
  margin: 5px;
}

HTML:

<html>
  <body>
    <div class="myChartDiv">
      <canvas id="myChart" width="600" height="400"></canvas>
    </div>
    <div id="chartLegend"></div>
  </body>
</html>

Leave a comment