getTableRowIndex not working with multiple controlwrapper

408 views
Skip to first unread message

Tanmoy (Cloud Engineering)

unread,
Nov 28, 2011, 3:04:35 AM11/28/11
to Google Visualization API
I am finding that in case of multiple controls (ControlWrapper) being
bound to a single chart (ChartWrapper) for a dashboard, the
getTableRowIndex does not return the correct row number from the
original DataTable when used to get the row number of selected row
(getSelection).

If there is only a single control, then it works fine, however if
there are multiple controls, either specified together (using an
array) or separately (by chaining bind function) then the row index
returns incorrectly for the 1st control.

e.g. based on the Google Playground example
______________________

Ex1.) the ChartWrapper - barChart is bound to only 1 control -
cityPicker

new
google.visualization.Dashboard(document.getElementById('dashboard')).
bind(countryPicker, regionPicker).
bind(regionPicker, cityPicker).
bind(cityPicker, barChart).
draw(data);
}

If a value is selected in countryPicker or regionPicker then the row
index returned on selected a raw is as per the 'visible' row index and
NOT the original row index in the DataTable.
If a value is selected in cityPicker then it selecting a row returns
the correct row index.
______________________

Ex2.) the ChartWrapper - barChart is bound to multiple controls

new
google.visualization.Dashboard(document.getElementById('dashboard')).
bind([countryPicker, regionPicker, cityPicker], barChart).
draw(data);
}

If a value is selected in countryPicker then getTableRowIndex returns
INCORRECT row index.
However, if regionPicker or cityPicker are used, then it returns
correct row index.
______________________

Ex3.) the ChartWrapper - barChart is bound to multiple controls and
order is changed

new
google.visualization.Dashboard(document.getElementById('dashboard')).
bind([regionPicker, countryPicker, cityPicker], barChart).
draw(data);
}

If a value is selected in regionPicker then getTableRowIndex returns
INCORRECT row index.
However, if countryPicker or cityPicker are used, then it returns
correct row index.

Any ideas or suggestions are welcome..

Roni Biran

unread,
Nov 28, 2011, 3:25:25 PM11/28/11
to google-visua...@googlegroups.com
can you send a non working full scale sample?



--
You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
To post to this group, send email to google-visua...@googlegroups.com.
To unsubscribe from this group, send email to google-visualizati...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-visualization-api?hl=en.


Riccardo Govoni ☢

unread,
Nov 28, 2011, 5:05:18 PM11/28/11
to google-visua...@googlegroups.com
I'm not sure I understand completely what the issue is, but when dealing with selection events you should resolve the index of the selected row/column against the same table that was used to draw the chart where selection occurred.

In a dashboard, the input datatable that you pass to dashboard.draw() is processed by the controls that are part of the dashboard and then ultimately served to the charts for drawing (after all the constraints defined by the controls were applied).

So if a chart fires a selection event and you resolve the row/column index contained in the event against the datatable you initialized the dashboard with, it probably won't work because any control in between might have filtered out some of the rows, therefore altering their indexes.

The correct way to figure out the selected row is to ask the chart itself for the Datatable it was drawn with, and use that instead.

In your example 1, if barChart fires a selection event, use barChart.getDataTable() to retrieve the table the chart was drawn with and resolve the selected row index against that one.

Does it make sense?
- R.

Tanmoy (Cloud Engineering)

unread,
Nov 28, 2011, 10:32:58 PM11/28/11
to google-visua...@googlegroups.com
To recreate, select the last row in the table (City = Nice).
It displays the rowIndex in the DataTable. 

1. Filter Country = France
    row index 3 instead of 8.

2. Filter Region = Provence
    row index 1 instead of 8

3. Filter City = Nice
    row index 8 as expected

<!--
You are free to copy and use this sample in accordance with the terms of the
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>
      Google Visualization API Sample
    </title>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load('visualization', '1.1', {packages: ['controls']});
    </script>
    <script type="text/javascript">
      function drawVisualization() {
        // Prepare the data
        data = google.visualization.arrayToDataTable([
          ['Country', 'Region/State', 'City', 'Population'],
          ['USA', 'California', 'San Francisco', 776733],
          ['USA', 'California', 'Los Angeles', 3694820],
          ['USA', 'California', 'Mountain View', 70708],
          ['USA', 'New York', 'New York', 8175173],
          ['USA', 'New York', 'Albany', 857592],
          ['France', 'Ile-de-France', 'Paris', 2193031],
          ['France', 'Ile-de-France', 'Orly', 21372],
          ['France', 'Provence', 'Marseille', 852395],
          ['France', 'Provence', 'Nice', 348556]
        ]);
        
        // Define category pickers for 'Country', 'Region/State' and 'City'
        var countryPicker = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control1',
          'options': {
            'filterColumnLabel': 'Country',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false    
            }
          }
        });
      
        var regionPicker = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control2',
          'options': {
            'filterColumnLabel': 'Region/State',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false    
            }
          }
        });
        
        var cityPicker = new google.visualization.ControlWrapper({
          'controlType': 'CategoryFilter',
          'containerId': 'control3',
          'options': {
            'filterColumnLabel': 'City',
            'ui': {
              'labelStacking': 'vertical',
              'allowTyping': false,
              'allowMultiple': false    
            }
          }
        });
        
        // Define a bar chart to show 'Population' data
        var barChart = new google.visualization.ChartWrapper({
          'chartType': 'Table',
          'containerId': 'chart1',
          'options': {
            'width': 400,
            'height': 300,
            'chartArea': {top: 0, right: 0, bottom: 0}
          },
          // Configure the barchart to use columns 2 (City) and 3 (Population)
          'view': {'columns': [0,1,2,3]}
        });
        
google.visualization.events.addListener(barChart, 'select', function () {
        var sel = barChart.getChart().getSelection();
rw = barChart.getDataTable().getTableRowIndex(sel[0].row);
alert(rw);
});

// Create the dashboard.
        new google.visualization.Dashboard(document.getElementById('dashboard')).
bind(countryPicker,regionPicker).
bind(regionPicker, cityPicker).
bind(cityPicker, barChart).
        draw(data);
      }

      google.setOnLoadCallback(drawVisualization);
    </script>
  </head>
  <body style="font-family: Arial;border: 0 none;">
    <div id="dashboard">
      <table>
        <tr style='vertical-align: top'>
          <td style='width: 300px; font-size: 0.9em;'>
            <div id="control1"></div>
            <div id="control2"></div>
            <div id="control3"></div>
          </td>
          <td style='width: 600px'>
            <div style="float: left;" id="chart1"></div>
            <div style="float: left;" id="chart2"></div>
            <div style="float: left;" id="chart3"></div>
          </td>
        </tr>
      </table>
    </div>
  </body>
</html>

Riccardo Govoni ☢

unread,
Nov 29, 2011, 1:36:41 AM11/29/11
to google-visua...@googlegroups.com
Ok, I got it now.

The problem you are experiencing is due to the fact that getTableRowIndex() only resolves row indexes in the immediate parent of the DataView you are calling it onto. As the documentation says "Returns the index in the underlying table (or view)".

In the case of dependent controls, like in your example, multiple controls operating in sequence can result in the chart receiving a DataView which is the composed result of multiple DataViews chained onto each other. For this reason getTableRowIndex() will not give the result you want, since it doesn't resolve the whole chain, but only goes one level deep.

Normally there is no need to resolve the selected row index against the original datatable the dashboard was initialized with, since you can always access the datatable which is local to the chart via the getDataTable() method. Your example could change into:

google.visualization.events.addListener(chart, 'select', function () {
  var sel = chart.getChart().getSelection();
  if (sel && sel.length) {
    alert('You selected the city ' + chart.getDataTable().getValue(sel[0].row, 2));
  }
});

If anyway, you need to resolve the selected index against the original datatable, there is an undocumented dataview.getUnderlyingTableRowIndex() method that does what you need (resolves row indices recursively through a chain of dataviews). However, I'd be interested in knowing what your use case is, since so far we never encountered a case where such method was necessary (aside from internal needs). Note that being undocumented, it can go away anytime without warning.

- R.

--
You received this message because you are subscribed to the Google Groups "Google Visualization API" group.
Reply all
Reply to author
Forward
0 new messages