带有过滤器和 DataView 的 Google 可视化仪表板

Posted

技术标签:

【中文标题】带有过滤器和 DataView 的 Google 可视化仪表板【英文标题】:Google Visualization Dashboard with filter and DataView 【发布时间】:2018-02-23 11:37:57 【问题描述】:

我有一个看起来像这样的 DataTable:

+-------+---------+--------+
| month |  name   | income |
+-------+---------+--------+
| Jan   | Alice   | $5,000 |
| Feb   | Alice   | $3,000 |
| Mar   | Alice   | $4,500 |
| Jan   | Bob     | $2,750 |
| Feb   | Bob     | $8,000 |
| Mar   | Bob     | $1,000 |
| Jan   | Charlie | $3,500 |
| Feb   | Charlie | $4,100 |
| Mar   | Charlie | $3,900 |
  ...       ...       ...

我希望显示一个带有一个 ChartWrapper 和一个 ControlWrapper 的 Google 可视化。

ChartWrapper 将显示一个表格,但我只希望此表格显示最近一个月。为此,我在 ChartWrapper 上使用.setView()

ControlWrapper 将在 name 列上包装 CategoryFilter。

我遇到的问题是,当我尝试选择一个名称时,它会抛出一个错误:Invalid row index ... Should be in range [0-...]

我相信我遇到了这个问题,因为setView 接受要显示的静态行数组,但是如果表格被过滤,那么要显示的行将会不同。我像这样打电话给setView

var recentRows = dataTable.getFilteredRows([
    
        "column": 2,
        "minValue": dataTable.getColumnRange(2).max
    
]);
chartWrapper.setView(
    "rows": recentRows
);

【问题讨论】:

【参考方案1】:

使用Dashboard控件时,ChartWrapperControlWrapper 需要同步并使用相同的数据集

如您所见,仅在图表上设置 view 属性会引发此问题

要更正,请使用DataView 来绘制仪表板, 如以下工作 sn-p 所示...

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

function drawChart() 
  var data = google.visualization.arrayToDataTable([
    ['month', 'name', 'income'],
    [0, 'Alice', 5000],
    [1, 'Alice', 3000],
    [2, 'Alice', 4500],
    [0, 'Bob', 2750],
    [1, 'Bob', 8000],
    [2, 'Bob', 1000],
    [0, 'Charlie', 3500],
    [1, 'Charlie', 4100],
    [2, 'Charlie', 3900]
  ]);

  var control = new google.visualization.ControlWrapper(
    controlType: 'CategoryFilter',
    containerId: 'control',
    options: 
      filterColumnLabel: 'name',
      ui: 
        allowTyping: false,
        allowMultiple: true
      
    
  );

  var chart = new google.visualization.ChartWrapper(
    chartType: 'Table',
    containerId: 'chart'
  );

  var view = new google.visualization.DataView(data);
  view.setRows(data.getFilteredRows([
    column: 0,
    minValue: data.getColumnRange(0).max
  ]));

  var dashboard = new google.visualization.Dashboard(
    document.getElementById('dashboard')
  );
  dashboard.bind(control, chart);
  dashboard.draw(view);
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="control"></div>
<div id="chart"></div>

另一个选择是使用仪表板 独立绘制每个包装器, 然后监听控件上的statechange事件, 并相应地绘制表格

请参阅以下工作 sn-p...

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

function drawChart() 
  var data = google.visualization.arrayToDataTable([
    ['month', 'name', 'income'],
    [0, 'Alice', 5000],
    [1, 'Alice', 3000],
    [2, 'Alice', 4500],
    [0, 'Bob', 2750],
    [1, 'Bob', 8000],
    [2, 'Bob', 1000],
    [0, 'Charlie', 3500],
    [1, 'Charlie', 4100],
    [2, 'Charlie', 3900]
  ]);

  var control = new google.visualization.ControlWrapper(
    controlType: 'CategoryFilter',
    containerId: 'control',
    dataTable: data,
    options: 
      filterColumnLabel: 'name',
      ui: 
        allowTyping: false,
        allowMultiple: true
      
    
  );
  control.draw();

  var chart = new google.visualization.ChartWrapper(
    chartType: 'Table',
    containerId: 'chart',
    dataTable: data
  );

  google.visualization.events.addListener(control, 'ready', drawTable);
  google.visualization.events.addListener(control, 'statechange', drawTable);
  drawTable();

  function drawTable() 
    var filters = [
      column: 0,
      minValue: data.getColumnRange(0).max
    ];

    var selectedNames = control.getState().selectedValues;
    if (selectedNames.length > 0) 
      filters.push(
        column: 1,
        test: function (value, row, column, table) 
          return (selectedNames.indexOf(table.getValue(row, column)) > -1);
        
      );
    

    chart.setView(
      rows: data.getFilteredRows(filters)
    );
    chart.draw();
  
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="control"></div>
<div id="chart"></div>

【讨论】:

不幸的是,这解决了一个问题,但又产生了另一个问题,但我想我会找到另一个问题的新解决方案 :) 首先我有其他月份的原因是因为仪表板上的其他地方我显示了历史值的折线图。在过滤给定名称时(仅在表格中显示“当前”收入的单行),我希望折线图被过滤以显示该名称的历史值。因此,表格需要显示过滤器创建的视图的子视图。 对除表格之外的所有内容都使用仪表板,然后使用上面的第二个选项来绘制表格...

以上是关于带有过滤器和 DataView 的 Google 可视化仪表板的主要内容,如果未能解决你的问题,请参考以下文章

DataView 行过滤器表达式 C#

如何使用 DataView 的 RowFilter 使用关键字“IN”来过滤集合

DataView

C# 在 .NET 1.1 中将 DataView 转换为表(DataTable)

SlickGrid RemoteModel 与 Dataview 模型

使用过滤器抛出异常