NumberRangeFilter and null

164 views
Skip to first unread message

Bassa Safa

unread,
Sep 5, 2012, 4:38:07 AM9/5/12
to google-visua...@googlegroups.com
I tfound a strange behaviour with NumberRangeFilter when dealing with null values.

If the data-cell is null that is controlled by a NumberRangeFilter... then the row is not shown in the table. However if the data-cell is null that is controlled by a CategoryFilter... then it is shown. The expected behaviour is that the row should be shown until an explicit movement of the NumberRangeFilter is done (like CategoryFilter).

In my example below. I have null values for 'Michael' and 'Elisa' in a NumberRangeFilter and CategoryFilter respectivly. As you see when you run the code 'Elisa' is still shown until a category is chosen. 'Micheal' however isnt showed at all.

Is there a workaround to this problem?
//bassa

function drawVisualization() {
  // Prepare the data
  var data = google.visualization.arrayToDataTable([
    ['Name', 'Gender', 'Age', 'Donuts eaten'],
    ['Michael' , 'Male', null, 5],
    ['Elisa', null, 20, 7],
    ['Robert', 'Male', 7, 3],
    ['John', 'Male', 54, 2],
    ['Jessica', 'Female', 22, 6],
    ['Aaron', 'Male', 3, 1],
    ['Margareth', 'Female', 42, 8],
    ['Miranda', 'Female', 33, 6]
  ]);

  // Define a slider control for the Age column.
  var slider = new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'containerId': 'control1',
    'options': {
      'filterColumnLabel': 'Age',
      'minValue': null,
      'maxValue': null,
    'ui': {'labelStacking': 'vertical'}
    }
  });

  // Define a category picker control for the Gender column
  var categoryPicker = new google.visualization.ControlWrapper({
    'controlType': 'CategoryFilter',
    'containerId': 'control2',
    'options': {
      'filterColumnLabel': 'Gender',
      'ui': {
      'labelStacking': 'vertical',
        'allowTyping': false,
        'allowMultiple': false
      }
    }
  });

  // Define a Pie chart
  var pie = new google.visualization.ChartWrapper({
    'chartType': 'PieChart',
    'containerId': 'chart1',
    'options': {
      'width': 300,
      'height': 300,
      'legend': 'none',
      'title': 'Donuts eaten per person',
      'chartArea': {'left': 15, 'top': 15, 'right': 0, 'bottom': 0},
      'pieSliceText': 'label'
    },
    // Instruct the piechart to use colums 0 (Name) and 3 (Donuts Eaten)
    // from the 'data' DataTable.
    'view': {'columns': [0, 3]}
  });

  // Define a table
  var table = new google.visualization.ChartWrapper({
    'chartType': 'Table',
    'containerId': 'chart2',
    'options': {
      'width': '300px'
    }
  });

  // Create a dashboard
  new google.visualization.Dashboard(document.getElementById('dashboard')).
      // Establish bindings, declaring the both the slider and the category
      // picker will drive both charts.
      bind([slider, categoryPicker], [pie, table]).
      // Draw the entire dashboard.
      draw(data);
}

Bassa Safa

unread,
Sep 5, 2012, 5:23:30 AM9/5/12
to google-visua...@googlegroups.com
Another strange issue with this can be seen with this modified example below. Now there are two NumberRangeFilters: one for 'age' and the other for 'donuts eaten'. Observe how Aaron - who is the youngest (3 years old) - has a null value in eaten donuts. Aaron does not show up on the table... but the value 3 is still at the far most left part of the 'age'-slider.



function drawVisualization() {
  // Prepare the data
  var data = google.visualization.arrayToDataTable([
    ['Name', 'Gender', 'Age', 'Donuts eaten'],
    ['Michael' , 'Male', 12, 5],
    ['Elisa', 'Female', 20, 7],

    ['Robert', 'Male', 7, 3],
    ['John', 'Male', 54, 2],
    ['Jessica', 'Female', 22, 6],
    ['Aaron', 'Male', 3, null],

    ['Margareth', 'Female', 42, 8],
    ['Miranda', 'Female', 33, 6]
  ]);

  // Define a slider control for the Age column.
  var slider = new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'containerId': 'control1',
    'options': {
      'filterColumnLabel': 'Age',
    'ui': {'labelStacking': 'vertical'}
    }
  });
  

    // Define a slider control for the Age column.
  var slider2 = new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'containerId': 'control2',
    'options': {
      'filterColumnLabel': 'Donuts eaten',
    'ui': {'labelStacking': 'vertical'}
    }
  });

 
      bind([slider, slider2], [pie, table]).

asgallant

unread,
Sep 5, 2012, 10:18:04 AM9/5/12
to google-visua...@googlegroups.com
These are behaving exactly as expected.

In the first case, all controls impose their starting state on whatever they are bound to - this is by design.  NumberRangeFilters filter on numbers, and "null" is not a number, therefor it is automatically filtered out by NumberRangeFilters.  If you don't want the filter to be imposed on the initial draw of the dashboard, you would have to draw the filter separately, then bind it to the dashboard in a "statechange" event handler and redraw the dashboard.  See it in action here:


In the second case, the age filter has no way of knowing that Aaron's row is being filtered out by another filter.  The same effect would happen in your first case if you filtered out Aaron's row by typing an "M" in the string filter control.  If you want one control to effect another control, you have to bind them:

dash.bind([slider][slider2]); 

Bassa Safa

unread,
Sep 5, 2012, 4:55:01 PM9/5/12
to google-visua...@googlegroups.com
Hello Asgallant,

and thank you for your helpful example. =) Too bad that there is no way to unbind controls to dashboards (or is there)... because if the user change the state and then change it back to its starting point... then the "null" rows doesn't come back. Is there a way to unbind control to dashboards?

I'm still not convinced that this is expected behaviour. If NumberRangeFilter filters on number, and "null" is not a number --> it is automatically filtered out. But CategoryFilter filters on Object/primitive types. Is "null" an Object/primitive type? Why dont null get filtered out in CategoryFilter?

thanks again
bassam

Bassa Safa

unread,
Sep 5, 2012, 4:59:42 PM9/5/12
to google-visua...@googlegroups.com

asgallant

unread,
Sep 5, 2012, 7:56:54 PM9/5/12
to google-visua...@googlegroups.com
CategoryFilters also have a unfiltered state, which NumberRangeFilters do not.

Bassa Safa

unread,
Sep 6, 2012, 5:24:57 AM9/6/12
to google-visua...@googlegroups.com
Oh, then I understand =) Thanx again for all your help =)

By the way, I dont know if you noticed... The "dataTable: data" is not explicitly written in the API for ControlWrapper (in the example you posted earlier).
https://developers.google.com/chart/interactive/docs/gallery/controls#controlwrapperobject


    // Define a slider control for the Age column.
    var slider = new google.visualization.ControlWrapper({
        controlType: 'NumberRangeFilter',
        containerId: 'control1',
        dataTable: data,

asgallant

unread,
Sep 6, 2012, 9:37:13 AM9/6/12
to google-visua...@googlegroups.com
Yeah, I suspect the dev team did not intend controls to be used outside of dashboards, so they never documented it.  When using Dashboards, you are supposed to omit that parameter, so it sort of makes sense to leave it out.  On the other hand, if they left it undocumented deliberately, then technically you should not rely on it being there in future versions (though I highly doubt they will get rid of this particular feature, as it matches perfectly with the ChartWrapper set up and is likely what they use behind the scenes to feed the controls data).
Reply all
Reply to author
Forward
0 new messages