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.
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.
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();
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.
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);
const parameterName = 'Profit Bin Size';
const dashboard = tableau.extensions.dashboardContent.dashboard;
const parameter = await dashboard.findParameterAsync(parameterName);
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheetNames = worksheets.map((worksheet) => worksheet.name);
const worksheetName = 'Product Sales';
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
const worksheet = worksheets.find((worksheet) => worksheet.name === worksheetName);
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);
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);
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);
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);
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;
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.
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
);
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;
}
async function handlerFunction(filterEvent) {
const data = await filterEvent.getFilterAsync();
const selectedValues = data.appliedValues.map((value) => value.nativeValue);
return selectedValues;
}
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!
Sign up to never miss a post!
Sign up to never miss a post!
Want me to cover a specific topic? Let me know!
Leave a comment