Snippets for Popular Extensions API Patterns

Snippets for Popular Extensions API Patterns

May 17, 2021 - TableauExtensions API

When building dashboard extensions you'll find yourself writing the same snippets of code over and over again when you're doing certain patterns. Whether it's getting data, listening to marks, or saving settings. Here I've put together a list of some snippets I use most often to help you get started (and for myself to kickstart my own code from 😉).
Note: Many of these snippets will be using the await keyword so make sure their containing functions use the async keyword. You can learn more about async/await here.

Getting configuration information

Often you'll want to pull data from a particular worksheet or field to process in your extension. You'll also likely want to let your users decide which worksheet/filter/parameter to pull from instead of hard-coding them. Here are a few snippets for getting those values dynamically.

Save configuration to settings
tableau.extensions.settings.set("worksheet", worksheetName);
tableau.extensions.settings.set("parameter", parameterName);
tableau.extensions.settings.set("field", fieldName);
tableau.extensions.settings.set("filters", JSON.stringify(filterList)); // Store all settings as strings!
await tableau.extensions.settings.saveAsync();
Read configuration from settings
const settings = tableau.extensions.settings.getAll();
const worksheetName = settings.worksheetName;
const parameterName = settings.parameterName;
const fieldName = settings.fieldName;
const filterList = JSON.parse(settings.filterList);

Now that you know how to save and retrieve settings, you can replace all the hard-coded name variables below with data from your settings.

Get the names of all parameters
const dashboard = tableau.extensions.dashboardContent.dashboard;
const parameters = await dashboard.getParametersAsync();
// If you only want parameters of a certain type, you can filter on dataType:
// parameters = parameters.filter((parameter) => parameter.dataType === 'string');
const parameterNames = parameters.map((parameter) => parameter.name);
Get a parameter by name
const parameterName = 'Profit Bin Size';
const dashboard = tableau.extensions.dashboardContent.dashboard;
const parameter = await dashboard.findParameterAsync(parameterName);
Get the names of all worksheets
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheetNames = worksheets.map((worksheet) => worksheet.name);
Get a worksheet by name
const worksheetName = 'Product Sales';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
Get the names of all fields on a worksheet
const worksheetName = 'Product Sales';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
const data = await worksheet.getSummaryDataAsync();
// If you only want fields of a certain type, you can filter on dataType:
// const fields = data.columns.filter((column) => column.dataType === 'string');
const fields = data.columns.map((field) => field.fieldName);
Get unique values from a field on a worksheet by name
const dashboard = tableau.extensions.dashboardContent.dashboard;
const worksheet = dashboard.worksheets.find((worksheet) => worksheet.name === settings.worksheet);
const data = await worksheet.getSummaryDataAsync();
const fieldName = 'Sub-Category';
const field = data.columns.find((column) => column.fieldName === fieldName);
const members = new Set();
for (let mark of data.data) {
    members.add(mark[field.index].value);
}
console.log(members);
Get the names of filters on a worksheet
const worksheetName = 'Product Sales';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
const filters = await worksheet.getFiltersAsync();
const filterNames = filters.map((filter) => filter.fieldName);
Get the currently selected items in the filter
const worksheetName = 'Product Sales';
const filterName = 'Region';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
const filters = await worksheet.getFiltersAsync();
const myFilter = filters.find((filter) => filter.fieldName === filterName);
const selectedValues = myFilter.appliedValues.map((value) => value.nativeValue);
Get the range selected in a numerical filter
const worksheetName = 'Product Sales';
const filterName = 'SUM(Sales)';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
const filters = await worksheet.getFiltersAsync();
const myFilter = filters.find((filter) => filter.fieldName === filterName);
const min = myFilter.minValue.nativeValue;
const max = myFilter.maxValue.nativeValue;

Events

Another popular pattern is to listen to interactions done by the user and react to it and the data used. The following patterns are all around listening to these events. Notice that each event is only available on certain objects: filter-changed and mark-selection-changed only work on worksheets, parameter-changed only works with parameters, and settings-changed only works with settings.

Add event listener to a worksheet

You can find a list of events in the documentation.

const worksheetName = 'Product Sales';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
const unnregisterListneer = worksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, handlerFunction);
Handle mark selection events
async function handlerFunction(marksEvent) {
    const fieldName = 'Sub-Category';
    const data = await marksEvent.getMarksAsync();
    const field = data.data[0].columns.find((column) => column.fieldName === fieldName  );
    const marks = new Set();
    for (let mark of data.data[0].data) {
        marks.add(mark[field.index].nativeValue);
    }
    return marks;
}
Handle filter changes
async function handlerFunction(filterEvent) {
    const data = await filterEvent.getFilterAsync();
    const selectedValues = data.appliedValues.map((value) => value.nativeValue);
    return selectedValues;
}
Handle parameter value changes
async function handlerFunction(parameterEvent) {
    const data = await parameterEvent.getParameterAsync();
    const parameterValue = data.currentValue.nativeValue;
    return parameterValue;
}

I'll keep adding to this list periodically. Let me know what samples would help you get started building dashboard extensions!

Subscribe

Sign up to never miss a post!

Leave a comment

Your email address is optional and will not be published.

A picture of Keshia Rose.

About Me

Hi, I'm Keshia, a Senior Product Manager at Tableau with a love for building fun random apps and helping people solve problems. Keep coming back to my blog to learn how to use Tableau APIs and developer tools or to hear about other cool tech I'm learning about!
Subscribe

Sign up to never miss a post!

Topic Request

Want me to cover a specific topic? Let me know!