Code Monkey home page Code Monkey logo

embedding-api-v3-guide's Introduction

Migrating from Embedding JSAPI v1 or v2 to Embedding API v3 (Migration Guide)

The initial release of the Embedding API library (version 3.0) was made available as part of the Tableau 2021.4 launch. To find out about using the current version of the library (now 3.4), see the documentation for the Tableau Embedding API v3 documentation.

Introduction

With Tableau’s Embedding API v3, we have redesigned the experience for embedding to make your life easier, to modernize the experience, and to enable new functionality. (If you are unfamiliar with the JavaScript API v2, you can read its documentation.) Some parts of using the API are the same as the JavaScript API v2, and others have just slightly different syntax. But the biggest difference is the initialization of the viz, which uses web components. Web components are a standard available in all modern browsers, that allow you to add custom, and 3rd party, functionality to your web page using html syntax as easily as adding an image, link, or div. Using the web component technology, we have created a tableau-viz component that you can use to add visualizations to your web pages.

How to use this guide

This guide has a few goals:

  1. To help you understand key concepts of using the Embedding API v3
  2. to solicit feedback from our community on changes we intend to make
  3. to help you migrate existing content to v3.

If you have comments or feedback, please submit an Issue on this Github repository.

Roadmap

For information about the next release of the Tableau Embedding API (version 3.6), see the Tableau Embedding API v3 Developer Preview . The Developer preview includes new methods for programmatically exporting views directly from Tableau without requiring user intervention, support for custom error handling for connected apps, and create embedded workbooks from scratch, with or without a data source.

Strategies for adopting the Embedding API v3

  • Anywhere you are using the previous versions’ copy-paste embed code, we recommend replacing with the new copy-paste embed code which, as you will see below, uses the Embedding API v3.
  • If you are starting a new embedding project, you should use the Embedding API v3.
  • For existing JavaScript API v2 projects, we recommend migrating your code as your timeline allows, because the Embedding API v3 can enable more robust embedding and because we will eventually end support for the JavaScript API v2.

Getting Started (or replacing ‘Embed Code’ from previous versions)

In previous versions of Tableau Server, there existed a JavaScript API v1. It is almost exclusively used in the ‘embed code’ from Tableau Server’s Share dialog.

<script type='text/javascript' src='https://myserver/javascripts/api/viz_v1.js'></script>
<div class='tableauPlaceholder' style='width: 1500px; height: 827px;'>
    <object class='tableauViz' width='1500' height='827' style='display:none;'>
    <param name='host_url' value='https%3A%2F%2Fmyserver' /> 
    <param name='embed_code_version' value='3' />
    <param name='site_root' value='&#47;t&#47;Superstore' />
    <param name='name' value='MyView' />
    <param name='tabs' value='no' /><param name='toolbar' value='yes' />
    <param name='showAppBanner' value='false' /></object>
</div>

To migrate from the JavaScript API v1 to the new JavaScript API v3, you can copy the new embed code which will give you something like:

<script src = "https://myserver/javascripts/api/tableau.embedding.3.0.0-alpha.23.js"></script>
<tableau-viz id="tableauViz" 
    src="http://my-server/views/my-workbook/my-view" 
    device="phone" toolbar="bottom" hide-tabs>
</tableau-viz>

Check the documentation for the current version of the .js file.

You will notice that the syntax of v3 is just as easy to copy-paste into your html and appears simpler because of the component and its ability to customize the properties of the embedded viz without nesting elements. Another key benefit to v3 is how easy it is to go from this simple copy-paste embed scenario to one where you interact with the viz via API. You can get started with the API simply by pasting in the v3 version of the embed code and then start layering on interactions and listeners as you will see below.

Before we do that, let’s take a closer look at the key parts of initializing an embedded viz.

Access the API

Accessing the API happens similarly to v1 and v2: You simply include the correct .js file, this time including the tableau-3.js (or a variation of it) from your Server. As before, you can reference the .js from your on-premise Server, from Tableau Online, or from Tableau Public.

Initialize the API

In the JavaScript API v2, you initialize the viz by adding an empty div object to your html and then create a new tableau.Viz object referencing the div and the viz url. Example:

HTML (v2 - will also work in v3)

<div id='tableauViz'></div>

JavaScript (v2 - going away. For v3 JS initialization see Alternative Approach: Initialization via JavaScript)

let placeholderDiv = document.getElementById("tableauViz");
let src = "http://my-server/views/my-workbook/my-view";
let options = {}
let viz = new tableau.Viz(placeholderDiv, url, options);

In the Embedding API v3, the initialization step is simplified and can happen all inside of your html, thanks to the new tableau-viz web component:

HTML:

<tableau-viz id="tableauViz" 
      src='http://my-server/views/my-workbook/my-view'>
</tableau-viz>

Configuration:

To specify options on how to initialize the Viz in the JSAPI v2, you would add those to the options object that is included in the Viz object’s constructor’s arguments. In the Embedding API v3, you can simply add those as properties of the viz component:

<tableau-viz id="tableauViz" 
    src="http://my-server/views/my-workbook/my-view" 
    device="phone" toolbar="bottom" hide-tabs>
</tableau-viz>

Note: for properties that accept a variety of values, such as src, device, and toolbar the syntax is <property>=“<value>”. For properties which are boolean, you either include the flag, to effectively set it to true (as shown with hideTabs), or omit it, to effectively set it to false.

Here is the list of properties you can add to your viz object:

HTML Property JS Property Accepted Values Description
hide-tabs Viz.hideTabs boolean Indicates whether tabs are hidden or shown.
toolbar Viz.toolbar "top", "bottom", "hidden" Indicates the position of the toolbar or if it should be hidden
height Viz.height <string> (e.g. "800px" or "800") Can be any valid CSS size specifier. If not specified, defaults to the published height of the view.
width Viz.width <string> (e.g. "800px" or "800") Can be any valid CSS size specifier. If not specified, defaults to the published height of the view.
device Viz.device <string> Specifies a device layout for a dashboard, if it exists. Values can be default, desktop, tablet, or phone. If not specified, defaults to loading a layout based on the smallest dimension of the hosting iframe element.
instance-id-to-clone Viz.instanceIdToClone <string> Specifies the ID of an existing instance to make a copy (clone) of. This is useful if the user wants to continue analysis of an existing visualization without losing the state of the original. If the ID does not refer to an existing visualization, the cloned version is derived from the original visualization.
disable-url-actions Viz.disableUrlActions boolean Indicates whether to suppress the execution of URL actions. This option does not prevent the URL action event from being raised. You can use this option to change what happens when a URL action occurs. If set to trueand you create an event listener for the URL_ACTION event, you can use an event listener handler to customize the actions. For example, you can direct the URL to appear in an iframeon your web page. See URL Action Example.

When adding properties to the tableau-viz component, use the HTML Property name. When configuring via JavaScript (as explained below), use the JS Property.

Filtering during initialization

In JSAPI v2 you can specify filtering to occur, by specifying field-value in the url or options object. In the Embedding API v3, you can accomplish the same thing by add elements as children to your objects. You can also set an initial parameter value.

<tableau-viz id="tableauViz" 
    src="http://my-server/views/my-workbook/my-view" 
    device="phone" toolbar="bottom" hide-tabs>
    <viz-filter field="country" value="USA" />
    <viz-filter field="state" value="California,Texas,Washington"></viz-filter>
    <viz-parameter name="currency" value="dollars" />
    <viz-range-filter field="profit" min="0" max="10000"></viz-range-filter>
    <viz-relative-date-filter field="Date" anchor-date="March 17, 2001"
        period-type = "Year" range-type = "LastN" range-n = "2"></viz-relative-date-filter>
</tableau-viz>

For viz-range-filter and viz-relative-date-filter, use the properties from RangeFilterOptions and RelativeDateFilterOptions, but convert them to dash-casing.

One important difference is that in the JSAPI v2 the filters that were loaded on initialization were added to the url of the viz. This limited the amount of filters that could be added, because url’s have a maximum length of 2048 characters. In the Embedding API v3, the filtering occurs separately from the viz url, but still occurs on initial load.

Event listeners

You can also add event listeners to the object

<tableau-viz id="tableauViz" 
    src="http://my-server/views/my-workbook/my-view"
    onMarksSelected="handleMarksSelection">
</tableau-viz>

(In the above example, handleMarksSelection() is a function which is specified in the JavaScript somewhere

Alternative Approach: Initialization via JavaScript

There are some scenarios where you may prefer to configure and initialize the viz via JavaScript instead of the above HTML component approach. Here is an example that demonstrates all of the above functionality using JavaScript.

HTML:

<div id='tableauViz'></div>

JavaScript:

import {TableauViz} from '../tableau.embedding.3.0.0-alpha.23.js'

let viz = new TableauViz();

viz.src = 'http://my-server/views/my-workbook/my-view';
viz.toolbar = 'hidden';
viz.addFilter('Region', 'Central');
viz.addEventListener('marksSelected', handleMarksSelection);

document.getElementById('tableauViz').appendChild(viz); 

Important notes about the above approach:

  • new TableauViz() does not render the viz. It creates a viz object so that you can configure the viz before it renders. It renders when you add it to the DOM, through something like document.body.appendChild(viz);
  • You can use JavaScript’s built-in document object to choose where in your html you want to add the viz. The above example uses an empty div and getElementById similar to the JavaScript API v2 approach, but you may other approaches depending on your scenario. Read more about JavaScript’s document object.
  • All of the configuration options listed above as properties of the viz object, can be defined in the same manner as viz.toolbar above.
  • Changing the properties, as shown in this example, will re-render the viz if it is already rendered. This is especially important to note for filtering. The addFilter method is not intended to be used after the viz has been initialized, instead use applyFilterAsync (and the other Filtering methods when appropriate).

Interacting with the Viz after initialization

All of the above discusses how to initialize the Viz and to configure it during initial load. You will likely want to interact with the Viz — filter, add/remove event listeners, change parameters, query data, etc. — after the Viz loads. The experience for accomplishing those things is very similar to the JavaScript API v2, except where noted below.

Accessing the Viz object

If you initialized the Viz viz JavaScript, then you already have a Viz object which you can interact with. For example:

import {TableauViz} from '../tableau.embedding.3.0.0-alpha.23.js'

let viz = new TableauViz();

viz.src = 'http://my-server/views/my-workbook/my-view';
viz.toolbar = 'hidden';
viz.addFilter('Region', 'Central');
viz.addEventListener('marksSelected', handleMarksSelection);

document.getElementById('tableauViz').appendChild(viz);

// Later
let sheet = viz.workbook.activeSheet;
sheet.applyFilterAsync("Container", ["Boxes"], FilterUpdateType.Replace);

But if you created a object in your html, you need to use document.getElementById to access the viz in your JavaScript:

let viz = document.getElementById('tableauViz');

// Later

let sheet = viz.activeSheet;
sheet.applyFilterAsync("Container", ["Boxes"], FilterUpdateType.Replace);

Note: In both of the above examples, the Viz will not be ‘interactive’ immediately after you initialize the Viz object. If you plan on filtering or doing some interaction immediately after initialization you should use the onFirstInteractive event listener to ‘wait’ for the viz object to be ready. This was also true in the JavaScript API v2.

Accessing other Objects and Namespaces

The relationship between objects/namespaces in v3 remains the same as in the JavaScript API v2. However, the syntax follows modern JavaScript practices and treats related objects as properties instead of returning them in getter methods. For example, to access the activeSheet’s worksheets in the JavaScript API v2, you would previously use

viz.getActiveSheet().getWorksheets();

In v3, you use

viz.activeSheet.worksheets;

The only exception to this is when calling an asynchronous method, such as getUnderlyingDataAsync() which keeps the same syntax as in v2. The reference will list the appropriate properties and methods for each Namespace.

In v2, many methods returned a collection of objects instead of a native array, allowing you to call .get to find the individual object that you wanted to act upon. For example:

let sameSheet = workbook.getPublishedSheetsInfo().get("Sheet 1");

In v3, these properties return native JavaScript arrays and you can use JavaScript’s .find to access the individual object:

let sameSheet = workbook.publishedSheetsInfo()
    .find(sheet => sheet.name == "Sheet 1");

Querying Data

In v2, getUnderlyingDataAsync() was deprecated and only available in Tableau 2020.1 or earlier. Therefore, it is not available in v3. Instead use getUnderlyingTablesAsync() and getUnderlyingTableDataAsync().

getSummaryDataAsync() remains in v3 with the same syntax. However, the following options have been added to getSummaryDataOptions.

Option Accepts Description
columnsToIncludeById int[] (columnID) Allows you to specify the list of columnIDs to return
maxRows int Returns the first set of rows up to the number specified
onlyFormattedValues bool Only return the formatted values (as specified by the viz author) and not the native values
onlyNativeValues bool Only return the native values and not the formatted values

There are also two new supporting additions:

  • getSummaryColumnsInfoAsync(): returns only the Column info for when you just need to retrieve metadata about the columns.
  • fieldID property of Column object: for use in columnsToInclude.

Things that remain the same

Filtering, Selecting Marks, and Changing Parameters

Filtering, selecting marks, and changing parameters after initialization remain the same:

worksheet.applyFilterAsync("Product Type", "Coffee", 
    FilterUpdateType.Replace);
workbook.changeParameterValueAsync("Product Type", "Coffee");

changeParameterValueAsync is available from Tableau Server 2022.3, Use tableau.embedding.3.3.0.js version for this functionality.

worksheet.selectMarksByValueAsync("Product", ["Caffe Latte"], 
    SelectionUpdateType.Replace);

Event Listeners

Adding and removing event listeners after initialization remains the same:

viz.addEventListener("marksSelection", function (marks) {
   changeMySelectionUI(marks);
});
viz.removeEventListener("marksSelection", changeMySelectionUI);

embedding-api-v3-guide's People

Contributors

d45 avatar ewaldhofman-sf avatar hackwithharsha avatar illonage avatar jacalata avatar keshiarose avatar kovner avatar lgraber avatar seanmakesgames avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

embedding-api-v3-guide's Issues

Get Notification When the Viz failed to load

The current version of the JS API offers the possibility to get a notification when the Viz object is ready (https://help.tableau.com/current/api/js_api/en-us/JavaScriptAPI/js_api_concepts_initializing.htm#get-notification-when-the-viz-object-is-ready) but there is not reliable way to have such notification when the Viz fails to load.

This can happen for a number of reasons (connectivity issue with the Tableau instance, Viz URL that changed, ...) and we'd like to be able to set up an asynchronous callback that would be called when the Viz fails to load to display an error message to the user instead of the blank screen that happens in this case.

We're currently using the workaround explained in the last answer of this post:
https://community.tableau.com/s/question/0D54T00000CWejqSAD/javascript-api-catching-errors
but we'd like a more practical/reliable option (like the "onFirstInteractive" event).

Random 16 LOGIN_FAILED errors trying to embed Vizs with JWT tokens

We have random "16" (LOGIN_FAILED) errors trying to display embedded Vizs with a token: everything in our tokens (connected app credentials, audience, subject, ...) is valid but we're hit with those random errors.

It can happen on any Viz we try to embed. From our side it really looks like an IP ban: on a given computer/IP address we'll start having those "16" errors at some point in the day and then we'll no longer be able to embed any Viz until the next morning, even if we use another connected app/subject (different Tableau user). The exact same connected app credentials/audience/subject/... is still working properly on another computer.

We have this issue on our dub01 Tableau Online site, one of our customers is also having this issue on their us-east Tableau Online site (Embedding API v3.2) but we've never been able to reproduce this issue in the Tableau Online 2022.3 preview site (Embedding API v3.3) until today when one of our developers is now unable to display any embedded Viz on this site as well.

Is there any restriction on the number of tokens a given IP address can use per day/24h period ?

Worksheet.applyRangeFilterAsync function stopped throwing errors when the filterName is invalid

Embedding API used: https://online.tableau.com/javascripts/api/tableau.embedding.3.latest.min.js
Tableau site used: 2022.4 Tableau Online preview site (10ax)

The Worksheet.applyRangeFilterAsync function doesn't throw any error if the "filterName" doesn't match any existing filter in the opened Worksheet.

An error is properly thrown if we open a Worksheet from a 2022.3 Tableau Online site instead. This used to work a few weeks/days ago on the same Tableau Online site.

Reproduction code:
https://glitch.com/edit/#!/heathered-lofty-marquess

Clearing session or cookies on PageRefresh

Hi Team,

In the following web page, we are rendering two visualizations.. Initially, It will render both the visualizations when our web server is up and serving tokens.. However, when our web server is down and failed to send token on web page refresh, there is no token and the first visualization will throw an error like 10084 which is perfectly fine and then second visualization is rendering using previous session cookies that were stored earlier… I think, you might have clear cookies or session tokens on page refresh. As there is no way to control cookies in Javascript for an Iframe as far as I know.

Check following screenshot.. Happy to connect and provide more information on this if required. It would be great, if you could release a some patch fix in Tableau Embedding API.

Feedback_1

changeParameterValueAsync with v3

Hello,

I have a problem with v3 embedding-api,
It's an Angular project.
I import tableau with:
<script type="module" src="https://embedding.tableauusercontent.com/tableau.embedding.3.0.0.min.js"></script>

Here is my html:
<tableau-viz id="tableau" src="myUrl" toolbar="hidden" hide-tabs> </tableau-viz>

And my typescript:

public ngAfterViewInit(): void {
    const vizTableau: any = document.getElementById('tableau');

    vizTableau.addEventListener('firstinteractive', () => {
        vizTableau.workbook.changeParameterValueAsync('XXX', 'YYY');
    });
}

I have the following error:
ERROR TypeError: vizTableau.workbook.changeParameterValueAsync is not a function

For information, the tableau is well displayed, and i can access to vizTableau.workbook.activeSheet.size.maxSize property for example.

In https://github.com/tableau/embedding-api-v3-guide#things-that-remain-the-same, in "Things that remain the same" section, there is an example of changeParameterValueAsync use. But it doesn't seem to work in my case.

Is this supposed to work? (vizTableau.getWorkbook() does not work too)
Do i have to use Initialization via JavaScript in this case ?

Thank you.

Worksheet.applyFilterAsync doesn't throw any error when the value doesn't belong to the filter's list of values

I have a basic embedded Worksheet with a filter on a "Region" dimension:
image

I use the Embedding API (v3.3) to apply a filter value for this "Region" filter, and purposefuly give a value that is not in this filter's list of values:
image
There is no visible error in the browser's console. The same workflow using the JavaScript API raises a "invalidFilterFieldValue" error.

Would it be possible for the Embedding API to throw an error in this case ? Thanks !

No documentation for error codes

I'm embedding using typescript with a JWT token.
I am receiving the response:
result: {errors: [{code: 10084}]}

Where is the documentation for these error codes?

Thanks in advance.

Dispose functionality

Right now, I can't initialize the viz with JS. So its a element, I would like to be able to dispose of the viz and load a new one. It seems to work without the dispose, but I can't apply filters once it's recreated.

I use jquery .load to add the to the DOM which works fine. I then can add event listeners etc. If I do a second .load overwriting the first the dashboard will load with the event listeners but I can't apply filters to this new object.

The old way:

https://help.tableau.com/current/api/js_api/en-us/JavaScriptAPI/js_api_sample_dynamic_load.htm

Not Implemented Error -- What does this mean?

Trying to use export functions to export via the new V3 embed. Viz loads fine, and I can access the element. Keep running into a "not-implemented: Not implemented" error.

Documentation literally says nothing about this error:
https://help.tableau.com/current/api/embedding_api/en-us/reference/enums/embeddingerrorcodes.html#notimplemented

Looking that the V3 source code (3.0.0.js), it looks like a FAIR amount of viz methods are just going to throw an error regardless:

pauseAutomaticUpdatesAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}

resumeAutomaticUpdatesAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}

toggleAutomaticUpdatesAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}

revertAllAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}

refreshDataAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}

showDownloadWorkbookDialog() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
showExportImageDialog() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
showExportPDFDialog() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
showExportDataDialog(worksheetInDashboard) {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
showExportCrossTabDialog(worksheetInDashboard) {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
showShareDialog() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
getCurrentSrcAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
redoAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}
undoAsync() {
    throw new api_shared_js_1.TableauError(Contract.EmbeddingErrorCodes.NotImplemented, 'Not implemented');
}

The documentation shows that these are all valid methods. What am I missing here?

Implement both Default/Desktop and Mobile device types

Hello, I was wondering if you know how to implement the Embedding API v3 with the possibility to use both the Default or Desktop device setting together with the Mobile option. It seems the v2 and v3 only allow to choose one of them, while the v1 from the 'share' dialog works for any device it is previously set.

Thanks!

addFilter in the initialization of Viz

I'm trying to add a filter in the initialization of a Viz using the viz.addFilter but it is not working.

import {TableauViz} from '../tableau.embedding.3.0.0-alpha.23.js'

let viz = new TableauViz();

viz.src = 'http://my-server/views/my-workbook/my-view';
viz.toolbar = 'hidden';
viz.addFilter('Region', 'Central');
viz.addEventListener('marksSelected', handleMarksSelection);

Is this not available in 3.0 or when will it be available.

Thanks.

FirstInteractive event randomly not raised on Google Chrome

Context of the issue

We're using the Embedding API to embed Tableau Vizs in a basic web application (static HTML page, vanilla JavaScript).
Those Vizs are initialized via JavaScript. We're adding a FirstInteractive event listener to the Viz to perform additional actions once the Viz is properly loaded (retrieve filters and parameters, ...).
We use the same page to display multiple embedded Vizs, one at a time.

Description of the issue

Randomly, the FirstInteractive event won't be raised, and the function given as the "listener" argument won't be called even if we wait for multiple minutes:

  • The issue can be systematically reproduced (see below) but can also happen randomly at any point
  • The issue seems specific to Chrome (we were able to reproduce the issue in Chrome 100, 101 and 102 but not in Firefox)
  • The issue is a bit different based on the OS: for Vizs that are subject to this issue, the issue will always occur when the first Viz is embedded on Windows but not on MacOS/Linux with headless Chrome. On all 3 OSes the issue will randomly appear when we repeatedly load Vizs in the same web page.
  • The issue occurs far more frequently when we first access the web application after launching Chrome - subsequent accesses to this web application (like refreshing the page for example) rarely experience the issue
  • The issue happens whether we launch Chrome with our existing user profile, with the "Guest" user profile or with a new temporary profile (when Chrome is launched by a chromedriver session)
  • The issue occurs more frequently for specific Vizs (see below) but we were able to reproduce the issue on Worksheets and Dashboards
  • The same Viz can be affected by the issue and then properly raise the event if we try to embed it two times in a row on the same web page (see below)
  • The issue seems to occur more frequently in larger web applications (in our complete web application built in ES6 JavaScript with typescript/webpack compared to the example application below)
  • The issue was reproduced on a Tableau 2022.1 and a Tableau 2022.2 preview site, with the 3.1 or 3.2 version of the Embedding API
  • The issue happens when we import the Embedding API from a CDN and when we import it locally as a resource of the web application
  • The issue happens with and without a valid JWT token added to the Viz object
  • We've never encountered this issue with the "onFirstInteractive" method in the JavaScript API in the exact same context (web application, embedded Viz, Tableau site, ...)

Reproduction Steps

A basic, static web application is hosted on a web server (in this example we're using python's http server by running "python -m http.server" in the web application folder) :

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Hello World!</title>
  <!-- Import the webpage's javascript file -->
  <script type="module" src="/script.js"></script>
</head>
<body>
  <div id="tableauViz"></div>
  <button id="load">
    Load
  </button>
</body>
</html>

script.js

import { TableauViz, TableauEventType } from "https://embedding.tableauusercontent.com/preview/tableau.embedding.3.latest.beta.js";
const vizs = [
  "https://10ax.online.tableau.com/t/<site>/views/<Workbook>/<Sheet>"
];
let viz;
async function firstInteractiveListener(_event) {
	console.log("First interactive ");
}
function loadViz() {
  viz = new TableauViz();
  viz.src = vizs[0];
  document.getElementById('tableauViz').innerHTML = '';
  document.getElementById('tableauViz').appendChild(viz);
  viz.addEventListener(TableauEventType.FirstInteractive, firstInteractiveListener);
}
const btn = document.getElementById("load"); // Get the button from the page
// Detect clicks on the button
if (btn) {
  btn.onclick = function () {
    loadViz();
  };
}
first_interactive.webm

Transcript of the video:

  • 00:00 I opened a new Chrome window with the "Guest" profile - this is not necessary to reproduce the issue (see above) but it is easier than closing/launching the Chrome application itself
  • 00:01 I log in to my Tableau site (2022.2 Preview in this case) since I'm not embedding Vizs with JWT tokens
  • 00:24 I open a new tab and access my web application
  • 00:31 I click on the "Load" button - this should load the embedded Vizs and log a "First interactive" message in the browser's console when the "FirstInteractive" event is raised. The embedded Viz here is one of the Vizs that most frequently encounters the issue, it's a Dashboard with a Text box and an image (no Worksheet).
  • 00:36 The Viz is fully loaded, the "FirstInteractive" event is not raised, and nothing is logged in the Console - this is the "first viz" behavior that only happens on Windows
  • 00:41 I click on the "Load" button again to replace the existing embedded Viz with a new one (the same Dashboard)
  • 00:43 The Viz is fully loaded, the "FirstInteractive" event is raised, and a "First interactive" message is logged in the Console
  • 00:45 I click on the "Load" button again to replace the existing embedded Viz with a new one (the same Dashboard)
  • 00:47 The Viz is fully loaded, the "FirstInteractive" event is not raised, and nothing is logged in the Console - this is the random issue that happens on all three OSes
  • 00:50 I click on the "Load" button again to replace the existing embedded Viz with a new one (the same Dashboard)
  • 00:52 The Viz is fully loaded, the "FirstInteractive" event is raised, and a "First interactive" message is logged in the Console (Chrome merges identical messages into a single line, and displays the number of identical messages with a number seen before the message itself)
  • 00:54 I click on the "Load" button again to replace the existing embedded Viz with a new one (the same Dashboard)
  • 00:56 The Viz is fully loaded, the "FirstInteractive" event is raised, and a "First interactive" message is logged in the Console

Web application:
firstInteractive.zip

Workbook used:
FirstInteractive_Workbook.zip

This issue is quite impactful for us as we're leveraging this "FirstInteractive" event to make sure that the Viz is properly loaded before automatically retrieving and displaying its information (Filters, Parameters, Data...).

Interact with Sets used as filters

We have Worksheets where Sets are defined and used in Rows:
image

When we open those Worksheets in Tableau we can chose the set values to exclude/includer to filter the data displayed:
image

I'd like to be able to programmatically retrieve/update those values with the Javascript Embedding API to filter the data displayed in our embedded Vizs exactly like what we're currently doing with actual filters.

Thanks !

Unable to initialize a Viz via JavaScript

Hi,

We're unable to initialize a Viz via the "JavaScript" method:

The following code
import {TableauViz} from './tableau-3.0.0.js'; let viz = new TableauViz();
produces this error:

Uncaught SyntaxError: The requested module './tableau-3.0.0.js' does not provide an export named 'TableauViz'

if we switch the import to:
import * as tableauApi from './tableau-3.0.0.js';
we end up with this error:
image (3)

Initializing the Viz using the <tableau-viz> HTML component works properly.

We're using the JS API available at https://embedding.tableauusercontent.com/dist-embedding/tableau.embedding.3.0.latest.beta.js

Incorrect float parameter value

I have an issue with the Embedding API retrieving the value of a float parameter in one of our Worksheets:
image

This Worksheet is embedded with the Embedding API and we use the following code to logs its parameters:
const sheet = viz.workbook.activeSheet;
const parameters = await viz.workbook.getParametersAsync();
console.log(parameters);

The Embedding API returns an incorrect value for this parameter:
image

The JavaScript API returns the expected value for the same Worksheet/parameter:
image

Retrieve the list of Actions of a Viz

We'd like to be able to retrieve the list of Actions (Worksheet/Dashboard > Actions in Tableau) for a Worksheet/Dashboard in an embedded Workbook:
image

We're looking for as much information as possible on those actions, like:

  • Type
  • Name
  • Run action on
  • Target
  • "Clearing the selection will"
  • Fields
  • URL for URL Actions

Thanks !

Feedback for Tableau Embedding API Team based on Tableau Server 2022.3 Release today

Feedback 1 :

In the following web page, we are rendering two visualizations.. Initially, It will render both the visualizations when our web server is up and serving tokens.. However, when our web server is down and failed to send token on web page refresh, there is no token and the first visualization will throw an error like 10084 which is perfectly fine and then second visualization is rendering using previous session cookies that were stored earlier… I think, you might have clear cookies or session tokens on page refresh. As there is no way to control cookies in Javascript for an Iframe as far as I know.

Check following screenshot.. Happy to connect and provide more information on this if required. It would be great, if you could release a some patch fix in Tableau Embedding API.

Feedback_1

Feedback 2:

There should be some kind of event or hook to get the HTTP status code of API request that TableauViz component is sending.. currently, There is no way to get this information due to cross-origin policy of iFrame. As you already have ‘firstinteractive’ hook. Is it possible to add some event to get this status code information ?

Feedback 3 :

It’s okay for developers to see these black screens with error code. But, our customers or users don’t know what they mean.. Either you could provide some fallback component or HTML element or implement feedback 2.. so, developers can handle these error messages differently based on HTTP Status Code.

Feedback 4 :

We are using only single token to render both the visualizations. Sometimes, one of the visualization will throw “Sign in to Tableau Server”.. If it’s token issue, It should throw for both the visualizations right ? as it is a single session. This is an intermittent issue happen once in a while. Don’t know why it happens. Same here also, I want my customers or users to see this “Sign in to Tableau Server”… I would handle it differently if we would have “Feedback 2” implemented.

Feedback_2

Please consider this feedback.. Let me know, If there is anything I can provide here.

It would be really great,, If you could fix or provide some solutions to all these issues and release a patch version of Tableau Embedding API sooner..

Implement a function in the Viz object to export Crosstab data

We're leveraging the Embedding API to embed Vizs and programmatically retrieve the Viz information (filters, parameters, data, ...) and compare it to expected values.

The Embedding API exposes a Viz.displayDialogAsync function that displays an export dialog.

For the Crosstab export, this function displays a modal on top of the embedded Viz with a "Download" button.
We can't interact with this "Download" button programatically as it is in an iframe (CORS issues).
We don't have this issue with the "Export Data" dialog for example since it opens a new browser Window.

We'd like to have a "Viz.exportCrosstabAsync" function that would take an Excel/CSV parameter and automatically download the Crosstab data in the selected format, exactly like the exportImageAsync shortcut.

Having hook or some event to know the HTTP status of iFrame

Issue 1

There should be some kind of event or hook to get the HTTP status code of API request that TableauViz component is sending.. currently, There is no way to get this information due to cross-origin policy of iFrame. As you already have ‘firstinteractive’ hook. Is it possible to add some event to get this status code information ?

Issue 2

It’s okay for developers to see these black screens with error code. But, our customers or users don’t know what they mean.. Either you could provide some fallback component or HTML element or implement feedback 2.. so, developers can handle these error messages differently based on HTTP Status Code.

Issue 3

We are using only single token to render both the visualizations. Sometimes, one of the visualization will throw “Sign in to Tableau Server”.. If it’s token issue, It should throw for both the visualizations right ? as it is a single session. This is an intermittent issue happen once in a while. Don’t know why it happens. Same here also, I want my customers or users to see this “Sign in to Tableau Server”… I would handle it differently if we would have “Feedback 2” implemented.

Following issues happen due to network issues or someother reason.. I don't want my production application users see this UI... If you provide status code or fallback component.. I would handle it differently.

Feedback_2

Feedback_1

Specify worksheet missing from csv and excel exports

Just discovered this is still a missing feature as of the 2022.4 release, and chiming in on this thread as I'd consider it a very notable missing feature that will significantly impact our plans to migrate to Embedding API.

V2 Feature

In the v2 JS API, the crosstab (csv) and Excel exports accept worksheetInDashboard as an argument in the function allowing you to specify which worksheet to export:

showExportCrossTabDialog(worksheetInDashboard)

Shows the Export Data dialog, which is currently a popup window. The worksheetInDashboard parameter is optional. If not specified, the currently active Worksheet is used. If there is no currently active Worksheet, the method throws an exception.

cf. https://help.tableau.com/current/api/js_api/en-us/JavaScriptAPI/js_api_ref.htm#viz_class

V3 Gap

In the v3 embedding API, the only available option to export data via CSV or Excel is to use
displayDialogAsync(dialogType: [TableauDialogType])

Display one of the export dialogs based on the dialogType parameter

cf. https://help.tableau.com/current/api/embedding_api/en-us/reference/interfaces/viz.html#displaydialogasync
& https://help.tableau.com/current/api/embedding_api/en-us/reference/enums/tableaudialogtype.html

This requires you to pass in "export-cross-tab". When using that method, it displays this export dialog that surfaces all the options to the user, and limits the ability to customize the export experience that we've built using the v2 API:
image

Use Cases

We use the v2 method pretty widely across our app. The most common use-cases are:

  1. Creating a "hidden" export worksheet on a dashboard to allow for pre-defining columns and/or pre-aggregated data. This can help prevent exposure of granular information that needs to remain inaccessible to users (i.e. PII data) while still allowing for exported ad-hoc data analysis.
  2. Limiting the worksheets to improve the user-experience. In a lot of cases, for example using a worksheet on a dashboard as a dynamic data-driven title: it doesn't make sense to export this title-page, but the naming convention may indicate to users that there is valuable data on that worksheet. Instead of allowing users to export all worksheets, we can limit to a subset of worksheets that only contain relevant and usable data.

How to apply filter for multiple worksheets in a dashboard

The tableau dashboard has a multiple worksheets (composite view). and all worksheets are filtered by same id. when i provide filter to dashboard it applies to only one worksheet. other filters are set to "None". and each worksheet has separate dropdown with same id's.

This is the code snippet

<tableau-viz id="tableauViz" src='server/views/workbook/workshhet' token={JWT} toolbar='hidden'> <viz-filter field="id" value="1de9ec86-xxxxx-4878-yyyy-609e55677ce2f"> </viz-filter> </tableau-viz>
how to apply filters to other worksheets ?

Restrict Adaptive Device Size to Width (ignore height)

Right now, Tableau chooses device size based on both height and width of the available browser space. Can you change this to just width?

I struggle to think of an application where it would be necessary to have a mobile view on a wide-yet-short monitor, and believe the majority of responsive/mobile design is based on width and ignores height

Applying filters after reloading `tableau-viz` element

I have an app with multiple pages, and one of them is a Tableau Embedded View that uses the tableau-viz element.

The first time I load the page with the tableau-viz element, I can apply filters using the applyFilterAsync method. If I leave the Tableau View page to visit another page in the app, and then return to the Tableau View page, applyFilterAsync no longer works.

The tableau-viz element is being removed/added to the DOM when I navigate away/to the Tableau View page.

Is there a way to dispose of the Viz object? I don't see the method in the documentation for v3, those this was possible in v2.

Invalid float native values retrieved in the summary data of Workbooks using a live data source

I have a Workbook that uses float and double values, and I want to retrieve its summary data with the Embedding API.

Float values are properly displayed in the Worksheet itself:
image

Downloading the data in Tableau also displays the expected values:
image

Using the Embedding API to retrieve the underlying data also produces the expected values:
image

Using the Embedding API to retrieve the summary data produces invalid native values:
image

I unfortunately can't share the Workbook used since it only happens for a live datasource: we no longer experience the issue if we switch to a data source extract.

It looks like the value we retrieve is the Java float approximation of "1.3" rounded to the 16th decimal:
image

Date/Date & Time native values retrieved as integers

We have a Worksheet with Date/Date & Time dimensions used with the 'D/M/YY' display:
image

When we try to retrieve the summary/underlying data of this Worksheet with the Embedding API we get integer native values in the YYYYMMDD format:
image

instead of the expected "date/datetime" type and Date values we get when we use another display option:
image

Link to the test project:
https://glitch.com/edit/#!/thoughtful-remarkable-lightning

The test Workbook:
Workbook date _ datetime.zip

Pass a Custom View name as a param on init

When first initialising the dashboard, it would be useful to be able to specify the name of a custom view to load too.

My scenario is that we have embedded dashboards in a website and allow the users to define the custom view via a URL param (e.g. http://example.com/dashboard?customview=myView)
Currently, I have to first load the dashboard, retrieve the list of custom views and then apply myView. This is doubling the load time for the page as it has to load the dashboard twice.
Ideally the API would allow me to pass myView as a parameter and load that view directly (or return an error that the view doesn't exist).

Be able to query for server admin rights

Using the API methods, how do I find a list of server admin users?

The back story is that we're using the embedded API to render dashboards within our app, and before we attempt to render, we verify that the user is defined onto the site using method "GET /api/api-version/sites/site-id/users?filter=userid". The problem with this is that some server admins have been testing the functionality and since they're not explicitly defined on the site (even though they have access to the dashboard), they get "you don't have access". The workaround is to add them onto the site explicitly.


The other thought is to add an inspectable return code from the embedding API that tells the app to display "you don't have access".

Permissions Retrieval for Toolbar Interactions

Will we be able to determine permissions for toolbar actions?

A lot of people (myself included) extrapolate the toolbar UI elements into their application. However determining what level of access people have through the REST API is very circuitous as permissions need to be checked against every level (project, workbook, view) and may not necessarily be user-specific.

In my opinion this would ideally be handled by the REST API*. However, if that's not viable a quick call to determine the availability of certain functions would be fantastic.

*My REST API suggestion would be either to

  1. Add permission as an optional response included in the call:
    GET /api/api-version/sites/site-id/users/user-id/workbooks
    or
  2. Add a separate API endpoint for permission retrieval that resolves to the user in question rather than the object in question

Precision of float values from the summary data different from the JavaScript API

The precision of float values returned by the Worsksheet.getSummaryDataAsync function has changed between the Javascript API and the Embedding API.

We have a basic Worksheet embedded with both APIs and we log its summary data using the same code:
const sheet = viz.workbook.activeSheet;
const data = await sheet.getSummaryDataAsync();
console.log(data);

For the same data point, in the Javascript API:
image
in the Embedding API:
image

displayDialogAsync for ExportData doesn't throw any error when the Viz is a Dashboard

When the current embedded Viz is a Dashboard and no Worksheet is selected the Download > Data button in the tooltip is greyed out:
image

Calling the displayDialogAsync(TableauDialogType.ExportData) function on this Viz doesn't display any dialog (since the Data button is greyed out) but doesn't throw any error either: would it be possible to throw an exception in this case so that we can warn our users that are expecting a dialog to be opened?

applyFilterAsync - Include option for context filtering

Ideally would like an option to include an option to apply a filter as a context filter, rather than only limited to a normal filter. I think this could be implemented like the "filterOptions: isExcludeMode" process - where the filter is specified.

Retrieve Relevant Values for Any Column

Currently in the v2 API in order to filter against a workbook, you can set any field in the dataset regardless of the makeup of the worksheet/dashboard you're filters. So for instance, if I run

worksheet.applyFilterAsync("Product Type", "Coffee",
    tableau.FilterUpdateType.REPLACE);

it will apply the filter regardless of whether or not Product Type is on my filter shelf. However, if Product Type is on my filter shelf and, for instance, set as a context filter, it will take that into account and apply the filter in context. This flexibility is extremely useful so I would appreciate if it can stay!

However, when retrieving filter values this "ask for any filter" approach does not work. When running
worksheet.getFiltersAsync() it only retrieves filters that have been set up in Tableau Desktop/Web-edit (understandably) or applied via the JS API.

Will there be a method available to retrieve relevant values for columns that haven't been added to the worksheet's filter shelf? Either a worksheet.getColumnValuesAsync("Product Type") or filtering the underlying data to specific columns (since this column may not exist on my level-of-detail as well)

WorksheetInDashboard parameter for the displayDialogAsync function

In the JavaScript API there's a worksheetInDashboard parameter for the showExportDataDialog function that allows us to specify which Worksheet we want to download data from when the current embedded Viz is a Dashboard.

We'd like a similar feature in the Embedding API: the displayDialogAsync function only takes an "export type" parameter and we're currently unable to display the dialog to download data of Worksheets other than the first one of an embedded Dashboard.

The Workbook.activateSheetAsync function changes the sheet displayed to a specific Worksheet instead of the Dashboard, something we'd like to avoid (changing the sheet displayed removes any filter applied/mark selected).

What is the <tableau-viz> property for FirstInteractive?

There is an example in the guide that shows we can add event listeners directly to the element via properties:

<tableau-viz id="tableauViz" 
      src="http://my-server/views/my-workbook/my-view"
      onMarksSelected="handleMarksSelection">
</tableau-viz>

Two questions:

  1. Is this functionality working? I see no where in the source code where "onMarksSelected" exists, so that's why I ask.
  2. What is (or will be) the equivalent of "FirstInteractive"?

Throw "Iframe has not been created yet" issue to developers instead of "Unexpected error during initialization"

In the following code block.

You are throwing an error IFrame has not been created Yet, which is okay. But, eventually what we get is an Unexpected error during initialization... In this case, I would like to see IFrame has not been created yet. In the catch block you can check the exception message and raise two different errors one for IFrame has not been created yet and another one is miscellaneous which is Unexpected error during initialization

This would be more helpful while integrating SPA frameworks like React in my case.

  public initializeViz(): void {
    try {
      const iframeWindow = this._iframe.contentWindow;
      if (!iframeWindow) {
        throw new TableauError(EmbeddingErrorCodes.InternalError, 'Iframe has not been created yet');
      }

      this._messenger = new CrossFrameMessenger(window, iframeWindow, this._frameUrl.origin);

      // We need the notification service for the bootstrap flow.
      this._dispatcher = new CrossFrameDispatcher(this._messenger);
      ApiServiceRegistry.get(this.embeddingId).registerService(new NotificationServiceImpl(this._dispatcher));

      const notificationService = ApiServiceRegistry.get(this.embeddingId).getService<NotificationService>(ServiceNames.Notification);
      const vizSizeKnownUnregister = notificationService.registerHandler(
        NotificationId.FirstVizSizeKnown,
        () => true,
        (model: FirstVizSizeKnownModel) => {
          this.handleVizSizeKnownEvent(model);
          vizSizeKnownUnregister();
        },
      );
      const vizInteractiveUnregister = notificationService.registerHandler(
        NotificationId.VizInteractive,
        () => true,
        (model: EmbeddingBootstrapInfo) => {
          this.handleVizInteractiveEvent(model);
          vizInteractiveUnregister();
        },
      );
      this._messenger.startListening();
      this._iframe.src = this._frameUrl.toString();
    } catch (e) {
      throw new TableauError(Contract.EmbeddingErrorCodes.InternalError, 'Unexpected error during initialization.');
    }
  }

changeParameterValueAsync is accepting display text instead of value ?

Hi Team,

Thanks for releasing Tableau 2022.3 for On-Premise Tableau Server customers..

Here is another issue with Tableau Embedding V3 with changeParameterValueAsync function. which is accepting display text instead of value.

workbook.changeParameterValueAsync("P.Show_Hide", 2)

Thank you !!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.