Simon Kibsgård
Simon Kibsgård

Reputation: 532

Google Charts: How do I add a label to grouped column chart

I have a column chart produced with the "classic" corechart package.

But, I don't understand how to put the column values as labels on top of each bar. (eg. 8.50 on the very first).

Here's my code:

google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
  var data = google.visualization.arrayToDataTable([
    [
      "",
      "Hamburgers",
      "Pizzas",
      "Flutes",
      "Wraps"
    ],
    ["29-04-2017", 8.50, 8.2, 8.4, 5.5],
    ["13-05-2017", 8.60, 8.32, 8.53, 5.67],
    ["12-06-2017", 8.30, 8.72, 8.13, 5.37],
    ["23-08-2017", 8.50, 8.22, 8.43, 5.57]

  ]);
  var options = {
    chart: {
      title: ' ',
      animation: {
        duration: 2000,
        easing: "out",
        startup: true
      }
    },
    legend: {position:'top'},
    hAxis: { format: "date" },
    vAxis: {
      format: 'decimal',
      viewWindow:{
        max:10,
        min:0
      }
    },
    height: 400,
    bars: 'vertical',
    colors: ["#0F5470", "#8EA3A4", "#3EB8BC", "#98D4F2"]
  };
  var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  chart.draw(data, options);
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Upvotes: 1

Views: 1552

Answers (1)

WhiteHat
WhiteHat

Reputation: 61275

you can use the annotation column role to add labels to the bars

the annotation column should follow the series column in the data table

see following working snippet
here, a DataView is used to add annotation columns for each series...

google.charts.load('current', {
  callback: drawChart,
  packages: ['corechart']
});

function drawChart() {
  var data = google.visualization.arrayToDataTable([
    [
      "",
      "Hamburgers",
      "Pizzas",
      "Flutes",
      "Wraps"
    ],
    ["29-04-2017", 8.50, 8.2, 8.4, 5.5],
    ["13-05-2017", 8.60, 8.32, 8.53, 5.67],
    ["12-06-2017", 8.30, 8.72, 8.13, 5.37],
    ["23-08-2017", 8.50, 8.22, 8.43, 5.57]
  ]);

  // build view
  var viewColumns = [0];
  $.each(new Array(data.getNumberOfColumns() - 1), function (index) {
    viewColumns.push(index + 1);
    viewColumns.push({
      calc: function (dt, row) {
        return dt.getFormattedValue(row, index + 1);
      },
      role: 'annotation',
      type: 'string'
    });
  });
  var view = new google.visualization.DataView(data);
  view.setColumns(viewColumns);

  var options = {
    chart: {
      title: ' ',
      animation: {
        duration: 2000,
        easing: "out",
        startup: true
      }
    },
    legend: {position:'top'},
    hAxis: { format: "date" },
    vAxis: {
      format: 'decimal',
      viewWindow:{
        max:10,
        min:0
      }
    },
    height: 400,
    bars: 'vertical',
    colors: ["#0F5470", "#8EA3A4", "#3EB8BC", "#98D4F2"]
  };

  var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  chart.draw(view, options);

  $(window).resize(function() {
    chart.draw(view, options);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>


EDIT

if you know the number of columns in the data table,
then you don't need to build them dynamically

the setColumns method takes an array,
each entry in the array can be a column index --> 0
or an object, if using a calculated column...

{
  calc: function (dt, row) {
    return dt.getFormattedValue(row, 1);
  },
  role: 'annotation',
  type: 'string'
}

in this case, we need to include the columns from the data table,
and a calculated column for each annotation column

see following working snippet...

google.charts.load('current', {
  callback: drawChart,
  packages: ['corechart']
});

function drawChart() {
  var data = google.visualization.arrayToDataTable([
    [
      "",
      "Hamburgers",
      "Pizzas",
      "Flutes",
      "Wraps"
    ],
    ["29-04-2017", 8.50, 8.2, 8.4, 5.5],
    ["13-05-2017", 8.60, 8.32, 8.53, 5.67],
    ["12-06-2017", 8.30, 8.72, 8.13, 5.37],
    ["23-08-2017", 8.50, 8.22, 8.43, 5.57]
  ]);

  // build view
  var view = new google.visualization.DataView(data);
  view.setColumns([
    0,  // <-- x-axis column index
    1,  // <-- first y-axis column index
    {   // annotation column for first y-axis column
      calc: function (dt, row) {
        return dt.getFormattedValue(row, 1);  // get formatted value from first y-axis column
      },
      role: 'annotation',
      type: 'string'
    },
    2,  // <-- second y-axis column index
    {   // annotation column for second y-axis column
      calc: function (dt, row) {
        return dt.getFormattedValue(row, 2);  // get formatted value from second y-axis column
      },
      role: 'annotation',
      type: 'string'
    },
    3,
    {
      calc: function (dt, row) {
        return dt.getFormattedValue(row, 3);
      },
      role: 'annotation',
      type: 'string'
    },
    4,
    {
      calc: function (dt, row) {
        return dt.getFormattedValue(row, 4);
      },
      role: 'annotation',
      type: 'string'
    }
  ]);

  var options = {
    chart: {
      title: ' ',
      animation: {
        duration: 2000,
        easing: "out",
        startup: true
      }
    },
    legend: {position:'top'},
    hAxis: { format: "date" },
    vAxis: {
      format: 'decimal',
      viewWindow:{
        max:10,
        min:0
      }
    },
    height: 400,
    bars: 'vertical',
    colors: ["#0F5470", "#8EA3A4", "#3EB8BC", "#98D4F2"]
  };

  var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  chart.draw(view, options);

  $(window).resize(function() {
    chart.draw(view, options);
  });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>


NOTE

the reason you cannot build the columns dynamically using a regular for loop,
is because we're assigning the column index in an object

in this case, a reference is saved to i

{
  calc: function (dt, row) {
    return dt.getFormattedValue(row, i);
  },
  role: 'annotation',
  type: 'string'
}

when the loop finishes and the columns are used in setColumns, all of the columns reference i, which is the last value of the loop

to use the value of i during the loop, instead of a reference to a i

then the object being built has to be inside a closure, or function

which is why the $.each statement is used in the original answer

this creates a closure and the value of index is used,
rather than a reference to index

$.each(new Array(data.getNumberOfColumns() - 1), function (index) {  // <-- this creates the closure...
  viewColumns.push(index + 1);
  viewColumns.push({
    calc: function (dt, row) {
      return dt.getFormattedValue(row, index + 1);
    },
    role: 'annotation',
    type: 'string'
  });
});

Upvotes: 1

Related Questions