2
votes

We have a workbook which contains two dashboards, the first contains one worksheet and the second contains four worksheets.

We're trying to pass filters in via the url (that part is ok) but we cannot get all the worksheets on the second dashboard to update.

The code loops through the dashboards, activating each in turn then calling a filterActiveSheet() method on each.

This method loops through each worksheet in turn, searches for a matching categorical filter with the same FieldName as the provided one and, when found, uses the applyFilterAsync() method to replace it with the provided one.

var options = {
    < snip >
    onFirstInteractive: function () {
        workbook = viz.getWorkbook();
        sheets = workbook.getPublishedSheetsInfo();
        for(s = 0; s < sheets.length; s++)
        {
            viz.getWorkbook().activateSheetAsync(s)
                .then(filterActiveSheet);
        }
    }
};

function filterActiveSheet(sheet) {
    for (ws = 0; ws < sheet.getWorksheets().length; ws++) {
        var worksheet = sheet.getWorksheets()[ws];
        worksheet.getFiltersAsync()
            .then(function(p) {
                var f = filters.split(';');
                for(y=0;y<f.length;y++){
                    var filter = f[y].split(':');                       
                    var filterType = $.grep(p, function(e){ return e.getFieldName() == filter[0]; });
                    if (filterType.length > 0) {
                        switch(filterType[0].getFilterType()) {
                            case tableau.FilterType.CATEGORICAL:
                                return worksheet.applyFilterAsync(filter[0], filter[1], tableau.FilterUpdateType.REPLACE);
                                break;
                            < snip >
                        }
                    }
                }
            });
    }
}

var viz = new tableauSoftware.Viz(placeholderDiv, url, options);

The problem we're seeing is that only one worksheet on each dashboard is being updated. Stepping through the JS in Chrome I can see the call to applyFilterAsync() the expected number of times which does not seem to cause an error, it simply doesn't seem to want to update all the filters/worksheets, just one on each dashboard.

Thoughts? Suggestions? Syntax errors?

1
My first thought would be to change the workbook and set the filter as Apply To All Using Data Source? Then you wouldn't need to iterate through with javascript. See onlinehelp.tableau.com/current/pro/desktop/en-us/….Sam M
Thanks for suggestion. Unfortunately that's what they're currently doing but, as there are multiple disparate data sources in the various sheets, it's a total pain and over-complicates things. I should add that this is just one small part of a much larger mechanism to handle these multi-worksheet dashdboards.Mike
Could using the newer filter feature in version 10 help to cover all the data sources? I think it's a filter feature called "Apply to all using related data sources".Sam M
Like I said, that is essentially what is being done but that apparently requires the creation of multiple aliases and just becomes a maintenance nightmare. The simple fact is that the javascript should work, it simply doesn't. The issues has now been raised with tableau as a bug report.Mike

1 Answers

1
votes

getPublishedSheetsInfo() returns a collection that is returning one worksheet and one dashboard the types of which can be determined by calling getSheetType(). You can't apply getFilterAsync() directly to a dashboard but have to iterate. Try something like:

if (sheet.getSheetType() === 'WORKSHEET') {
    sheet.getFiltersAsync().then(function(filters) {
        for (var x = 0; x < filters.length; x++) {                                   
            // do something
        }
    })
} else {
    // either in a dashboard or story
    var workSheetArray = sheet.getWorksheets();
    for (var i = 0; i < workSheetArray.length; i++) {
        workSheetArray[i].getFiltersAsync().then(function(filters) {
            for (var x = 0; x < filters.length; x++) {
                // do something
            }
        }
    }
}