B. Pal B. Pal - 4 months ago 24
Javascript Question

Google Charts X Javascript X HTML - Dropdown filters not functioning properly

I'm trying to create a chart with 3 dropdown filters associated to it. For the filters, i'm trying to use actual HTML dropdown lists instead of the CategoryFilters from the Google Charts library since i want to configure it as a filter for an HTML table to be added posteriorly.

The chart is drawn successfully and the filters themselves work as well. However, the obtained output isn't the one i desired. For instance, if i choose "Male" on the gender filter and "East" on the location filter, i should be able to view both columns, not one at a time like it happens. In other words, i wanna be able to add or remove columns/rows according to the options i chose. I suspect that the "setView" and "setOption" operations overwrite any previous configurations. I'd like to know how i could get around this. Any help would be appreciated!

Javascript code to draw chart and configure filters:

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

function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Age Range');//0
data.addColumn('number', 'Male');//1
data.addColumn('number', 'Female');//2
data.addColumn('number', 'East');//3
data.addColumn('number', 'West');//4
data.addColumn('number', 'Global');//5

//dummy data
//dados reais a serem adicionadas posteriormente
data.addRows([
['0-30', 20, 40, 55, 60, 70],
['31-60', 40, 60, 70, 75, 80],
['61-90', 60, 65, 80, 85, 90]
]);

// chart colors
var colors = ["#00617F", "#0093C8", "#FA1414", "#A60202", "#000000"];

//chart options
var options = {
title: 'Average Sentiment',
colors : colors,
hAxis: {
title: 'Age Range'
},
vAxis: {
title: 'Sentiment',
viewWindow : {
max : 0,
min : 100
}
}
};

//chart definition
var chart = new google.visualization.ChartWrapper({
chartType: 'ColumnChart',
dataTable: data,
options: options,
containerId: 'chart_div'
});

//draws chart
chart.draw();

$('#genderfilt').change(setColumnsRows);
$('#locationfilt').change(setColumnsRows);
$('#agefilt').change(setColumnsRows);

function setColumnsRows() {
var gender = document.getElementById("genderfilt").value;
var location = document.getElementById("locationfilt").value;
var age = document.getElementById("agefilt").value;
var input= input:radio[name=field];

var rows = [];
for (var i = 0; i < data.getNumberOfRows(); i++) {
if ((data.getValue(i, 0) === age) || (age === 'All')) {
rows.push(i);
}
}

var columns = [0];
for (var i = 1; i <= 2; i++) {
if ((data.getColumnLabel(i) === gender) || (gender === 'All')) {
columns.push(i);
}
}
for (var i = 3; i < data.getNumberOfColumns(); i++) {
if ((data.getColumnLabel(i) === location) || (location === 'All')) {
columns.push(i);
}
}

var newColors = [];
for (var i = 1; i < columns.length; i++) {
newColors.push(colors[columns[i]]);
}

chart.setOption('colors', newColors);
chart.setView({'columns' : columns, 'rows' : rows});
chart.draw();
}

$(document).ready(function() {
$('input:radio[name=field]').change(function() {
if (this.value == '') {
chart.setView({'columns': [0,5]});
chart.setOption('colors', ["#000000"]);
}
else if (this.value == 'gender') {
chart.setView({'columns': [0,1,2]});
chart.setOption('colors', ["#00617F", "#0093C8"]);
}
else if (this.value == 'location') {
chart.setView({'columns': [0,3,4]});
chart.setOption('colors', ["#FA1414", "#A60202"]);
}
chart.draw();
});
});
}


HTML code:

<div class="container" id="dashboard">
<h2>Chart</h2>
<hr>
<center>
<table id="filters">
<tr>
<th>
<form id="names" align="left" name='test'>
<input type="radio" name="field" value="" checked>All
<input type="radio" name="field" value="gender" >Gender
<input type="radio" name="field" value="location">Location
</form>
</th>
</tr>
<tr>
<select id="genderfilt">
<option value="All">Choose Gender
<option value="Male">Male
<option value="Female">Female
</select>
</tr>
<tr>
<select id="locationfilt">
<option value="All">Choose Location
<option value="East">East
<option value="West">West
</select>
</tr>
<tr>
<select id="agefilt">
<option value="All">Choose Age Range
<option value="0-30">0-30
<option value="31-60">31-60
<option value="61-90">61-90
</select>
</tr>
</table>
<div id="chart_div"></div>
</center>
</div>


Fiddle: https://jsfiddle.net/kjn27f2r/

Answer

i would recommend combining all listeners into one function,
so you can keep up with everything, regardless of what changes.

see setColumnsRows in the following example...

also, you can rely on the google callback to know when the page is ready

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

function drawChart() {
  var data = new google.visualization.DataTable();
  data.addColumn('string', 'Age Range');//0
  data.addColumn('number', 'Male');//1
  data.addColumn('number', 'Female');//2
  data.addColumn('number', 'East');//3
  data.addColumn('number', 'West');//4
  data.addColumn('number', 'Global');//5

  //dummy data
  //dados reais a serem adicionadas posteriormente
  data.addRows([
    ['0-30', 20, 40, 55, 60, 70],
    ['31-60', 40, 60, 70, 75, 80],
    ['61-90', 60, 65, 80, 85, 90]
  ]);

  // chart colors
  var colors = ["#00617F", "#0093C8", "#FA1414", "#A60202", "#000000"];

  //chart options
  var options = {
    title: 'Average Sentiment',
    colors : colors,
    hAxis: {
        title: 'Age Range'
    },
    vAxis: {
        title: 'Sentiment',
        viewWindow : {
            max : 0,
            min : 100
        }
    }
  };

  //chart definition
  var chart = new google.visualization.ChartWrapper({
    chartType: 'ColumnChart',
    dataTable: data,
    options: options,
    containerId: 'chart_div'
  });

  //draws chart
  chart.draw();

  $('#genderfilt').change(setColumnsRows);
  $('#locationfilt').change(setColumnsRows);
  $('#agefilt').change(setColumnsRows);

  function setColumnsRows() {
    var gender = document.getElementById("genderfilt").value;
    var location = document.getElementById("locationfilt").value;
    var age = document.getElementById("agefilt").value;

    var rows = [];
    for (var i = 0; i < data.getNumberOfRows(); i++) {
      if ((data.getValue(i, 0) === age) || (age === 'All')) {
        rows.push(i);
      }
    }

    var columns = [0];
    for (var i = 1; i <= 2; i++) {
      if ((data.getColumnLabel(i) === gender) || (gender === 'All')) {
        columns.push(i);
      }
    }
    for (var i = 3; i < data.getNumberOfColumns(); i++) {
      if ((data.getColumnLabel(i) === location) || (location === 'All')) {
        columns.push(i);
      }
    }

    var newColors = [];
    for (var i = 1; i < columns.length; i++) {
      newColors.push(colors[columns[i]]);
    }

    chart.setOption('colors', newColors);
    chart.setView({'columns' : columns, 'rows' : rows});
    chart.draw();
  }
}
<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 class="container" id="dashboard">
   <h2>Chart</h2>
   <hr>
   <center>
      <table id="filters">
          <tr>
              <select id="genderfilt">
                  <option value="All">Choose Gender
                  <option value="Male">Male
                  <option value="Female">Female
              </select>
          </tr>
          <tr>
              <select id="locationfilt">
                  <option value="All">Choose Location
                  <option value="East">East
                  <option value="West">West
              </select>
          </tr>
          <tr>
              <select id="agefilt">
                  <option value="All">Choose Age Range
                  <option value="0-30">0-30
                  <option value="31-60">31-60
                  <option value="61-90">61-90
              </select>
          </tr>
      </table>
      <div id="chart_div"></div>
   </center>
</div>