使用ControlWrapper进行过滤时如何获取正确的google.visualization.Table#selection row index?

时间:2014-05-10 01:31:36

标签: google-visualization

以下工作正常(请参阅jsfiddle),除非通过其中一个控件包装器过滤表。似乎currentRow和rowIndex总是具有相同的数字,例如google.visualization.DataView#getTableRowIndex(currentRow)不做任何翻译;它只是吐出与传入的数字相同的数字。如何正确翻译行索引,以便可以从底层的google.visualization.DataTable获取所需的行?

function drawChart()
{
    var dataTable = new google.visualization.DataTable();
    dataTable.addColumn('date', 'Request Date');
    dataTable.addColumn('string', 'To Do');
    dataTable.addColumn('date', 'Target Complete Date');
    dataTable.addColumn('number', 'Duration');
    dataTable.addColumn('date', 'Date Completed');
    dataTable.addColumn('number', 'ID');

    dataTable.addRow([
        new Date(2014, 1, 24),
        'To do item 1',
        new Date(2014, 1, 27),
        3.5,
        new Date(2014, 1, 26),
        1000
    ]);

    dataTable.addRow([
        new Date(2014, 2, 24),
        'To do item 2',
        new Date(2014, 2, 27),
        1.5,
        new Date(2014, 2, 26),
        1001
    ]);

    dataTable.addRow([
        new Date(2014, 3, 24),
        'To do item 3',
        new Date(2014, 3, 27),
        7.5,
        new Date(2014, 3, 26),
        1002
    ]);

    dataTable.addRow([
        new Date(2014, 4, 24),
        'To do item 4',
        new Date(2014, 4, 27),
        4.5,
        new Date(2014, 4, 26),
        1003
    ]);

    dataTable.addRow([
        new Date(2014, 5, 24),
        'To do item 5',
        new Date(2014, 5, 27),
        2.5,
        new Date(2014, 5, 26),
        1004
    ]);

    //  Format the duration column so that it shows two decimal places.
    var durationFormatter = new google.visualization.NumberFormat({ 'fractionDigits': 2 });
    durationFormatter.format(dataTable, 3);     // Apply formatter to duration column

    //  Table chart
    var cssClassNames = {
        'headerRow': 'dataHeaderRow',
        'tableRow': 'dataTableRow',
        'oddTableRow': 'dataOddTableRow',
        'selectedTableRow': 'dataSelectedTableRow',
        'hoverTableRow': 'dataHoverTableRow',
        'headerCell': 'dataHeaderCell',
        'tableCell': 'dataTableCell',
        'rowNumberCell': 'dataRowNumberCell'
    };

    var tableChartOptions = {
        'cssClassNames': cssClassNames,
        'alternatingRowStyle': true,
        'page': 'enable',
        'pageSize': 10,
        'pagingSymbols': {
            prev: '<span class="fa fa-arrow-left"></span>',
            next: '<span class="fa fa-arrow-right"></span>'
        },
        'pagingButtonsConfiguration': 'auto',
        'sort': 'enable',
        'sortAscending': true,
        'sortColumn': 0,      //  <-- Initially sort by column 0: date column.
        'title': 'Completed To Do List',
        'width': '100%'
    };

    // Prevent the database ID (column 5 in underlying data table) from being 
    // displayed via a data view.
    var rawDataView_NoID = new google.visualization.DataView(dataTable);        
    rawDataView_NoID.setColumns([0, 1, 2, 3, 4]);

    var chartWrapper = new google.visualization.ChartWrapper({
        'chartType': 'Table',                            //  <-- google.visualization.Table
        'containerId': 'loggedInCompletedToDoChart_div',
        'options': tableChartOptions
    } );

    //  The chart must be ready before the select listener can be created.
    google.visualization.events.addListener(
        chartWrapper,
        'ready',
        function () {
            var visualization_table = chartWrapper.getChart();  //  <-- google.visualization.Table
            google.visualization.events.addListener(
                visualization_table,
                'select',
                function () {
                    //  Chart wrapper in this case is configured to allow only
                    //  a single row selection. Hence, an array of length 1.
                    var selection = visualization_table.getSelection()[0];
                    var currentRow, rowIndex, duration, entryId;
                    if (selection !== undefined) {
                        currentRow = selection.row;
                        rowIndex = chartWrapper.getDataTable().getTableRowIndex(currentRow);
                        duration = dataTable.getFormattedValue(rowIndex, 3); 

                        // entryId is available in underlying data table -- not in data view.
                        entryId = dataTable.getFormattedValue(rowIndex, 5);
                        alert(entryId); // Only correct when no filtering takes place.
                    }
                }
    );});

    // Define Filter controls
    var toDoFilter = new google.visualization.ControlWrapper({
        'controlType': 'StringFilter',
        'containerId': 'loggedInCompletedToDo_ToDo_SearchInputElement_div',
        'options': {
            'filterColumnLabel': 'To Do',
            'matchType': 'any'
    }});

    var durationFilter = new google.visualization.ControlWrapper({
        'controlType': 'NumberRangeFilter',
        'containerId': 'loggedInCompletedToDo_Duration_SearchInputElement_div',
        'options': {
            'filterColumnLabel': 'Duration',
            'ui': {
                'format': { 'fractionDigits': 2 },
                'step': 0.25
            }
    } } );

    // Create the dashboard.
    var dashboard = new google.visualization.Dashboard(
        document.getElementById('loggedInCompletedToDoDashboard_div')
    ).
    // Configure the filters to affect the chart content
    bind([ toDoFilter, durationFilter ], chartWrapper).
    // Draw the dashboard
    draw(rawDataView_NoID);
}

google.load('visualization', '1.0', {packages: ['table', 'controls']});
google.setOnLoadCallback(drawChart);

修改

我注意到问题只发生在传递给bind函数的第一个控件包装器上。换句话说,使用以下配置时,如果使用“待办事宜”过滤器,则行选择将停止正常工作:

    bind([ toDoFilter, durationFilter ], chartWrapper).

如果我交换过滤器的顺序,那么如果使用持续时间过滤器,行选择将停止正常工作:

    bind([ durationFilter, toDoFilter ], chartWrapper).

如果我按如下方式链接方法调用,则链中的第一个控件包装器对象会导致行选择无法正常工作(就像数组中的第一个控件包装器对象一样,上面做了),更糟糕的是,这样做会导致只需单击鼠标即可连续调用14次选择处理程序:

    bind(durationFilter, chartWrapper).
    bind(toDoFilter, chartWrapper).

根据API reference

绑定(控件,图表)

将一个或多个控件绑定到一个或多个其他仪表板参与者(图表或其他控件),以便在任何前者收集影响由仪表板管理的数据的编程或用户交互时重绘所有后者。返回仪表板实例本身,用于将多个bind()调用链接在一起。

控件 - 定义要绑定的控件的单个或一组google.visualization.ControlWrapper实例。

图表 - 一个或一个google.visualization.ChartWrapper实例数组,用于定义将由控件驱动的图表。

1 个答案:

答案 0 :(得分:4)

您可以通过引用传递给ChartWrapper的数据而不是尝试转换回原始DataTable来避免这种情况。改变这个:

currentRow = selection.row;
rowIndex = chartWrapper.getDataTable().getTableRowIndex(currentRow);
duration = dataTable.getFormattedValue(rowIndex, 3);

到此:

duration = chartWrapper.getDataTable().getFormattedValue(selection.row, 3);

此外,ChartWrappers现在本身支持“select”事件,因此您无需使用“ready”事件包装它们:

google.visualization.events.addListener(chartWrapper, 'select', function () {
    // selection handling
});