Auto refresh a Tableau Dashboard without Embedding
March 21, 2017
, , , , ,

counterI was casually sitting at my desk writing my first ever blog entry here when Tamás Földi walked past my desk. He asked me how much I know about Tableau and JavaScript, because he has a cool idea which he didn’t really manage to find the time to implement yet. He quickly briefed me into what he had in mind and off I went to start coding it. The idea is to place a little spinner or counter into a Tableau Dashboard and as often as the counter ticks call the refresh JavaScript API function to reload the data. All this without embedding the dashboard into an another page. And what if I tell you that this little gem can be reused without any changes in any Dashboards on any Server? I bet you want to see it action first, right? I knew that, so click here to see a live working demo. If you like what you see I’m sure you’ll also enjoy reading the rest of the post where I share how it’s all put together.

TL;DR – Auto refresh Tableau dashboard

We’ve developed it using the Tableau Web Data Connector trick explained here. Download and deploy this data connector to your Tableau Server once and you’ll be able to use it in any number of dashboard hosted on that server. To use it, insert a Web Page component to your dashboard and point the URL to the Web Data Connector. The solution only works when the dashboard is published to the Tableau Server and accessed through a browser. By default the counter will count down from 10 seconds then calls the refreshDataAsync API call to reload the data behind the dashboard before starting a new count down (Like how Russell did few years back). The counter can be customized (seconds, colors, size, etc.) in a user-friendly way with the use of parameters defined in Tableau Desktop. All this is achieved without the need to embed the Tableau Dashboard into any other web page, which is the beauty of this solution.

How many days until the Tableau On Tour Conferences?

How many days until the Tableau On Tour Conferences?

The usual solution

After a quick Google search I came to know that this requirement often comes up (don’t blame me that I needed Google for this, I’m coming from a Spotfire background, barely used Tableau before). Most solutions which are currently out there are floating around the following approach:

  • have a HTML page
  • embed a Tableau dashboard into that HTML page
  • use the refreshDataAsync() API call combined with a setInterval to do this on a regular basis

The main downside of this is that you need an extra HTML page, a web server which serves this page, someone familiar with HTML/JavaScript to set this up for all dashboards where it’s required, so all in all it is not really user-friendly and flexible.

A more user-friendly solution

If you are a regular reader of the DataBoss blog, you might already know what the secret ingredient is going to be: Tamás’ article from last year covers how the JavaScript API can be used with the help of a web data connectors and without embedding. Later Zen Master Chris DeMartini used this to embed fancy D3 charts or Bryant who played with the default data filters. If you are not familiar with the ‘magic’ head over here first to get caught up – I’ll wait for you right here.

Now that we are on the same page, let’s see the approach to tackle the problem:

  1. develop a standalone HTML file which has a visually appealing counter
  2. deploy this as a web data connector to your Tableau Server
  3. at this point you can add a Web Page component to your dashboard with its link pointing to the Web Data Connector
  4. the counter can be further customized to best fit your style

The good news is that I’ve already done the hard work for you for step 1, while step 2 you’ll only need to do once for each Tableau Server you wish to this on. Step 3 is the easiest step by far and can be done with the same ease for any number of dashboards. Last but not least, step 4 is completely optional the default values are working just fine but if you want to customize the counter you can do it.

How to install it

Grab the HTML file from here (view source here just so you can ensure I don’t have anything fishy in it) and copy it to a temporary location on your Tableau server. This file will need to be deployed as a web data connector. When logged in to your Tableau Server with remote desktop, you’ll need a command line prompt to run the import_webdataconnector command. In Tableau 10.x there are two ways to enable a Web Data Connector, but we’ll need to use the import method for this solution to work. That is because we are using the JavaScript API so we need the Web Data Connector to be running on the same host where Tableau Dashboard is served from, otherwise it would fail. For further details about Web Data Connectors check out the official documentation.

Long story short, here is how I imported my shiny connector:

You can ignore the warning about the deprecated command, it’s not going away any time soon. Note down the URL which was returned from the command. If you normally access the Tableau Server with a DNS address make sure to update the URL accordingly. Unless you use a custom port for running your Tableau Server (ie. anything apart from :80 for http:// and :443 for https://) you can leave out the port.

Once you have the final URL feel free to test it in any browser. You should see the green counter with the default 10 seconds label on it and while it’s not doing anything that’s normal at this point. If you see the green circle then you are good to proceed. The Tableau Dashboard is going to be the one which will start it once it is loaded. If you are familiar with your browser’s Developer Tools you can manually start it with the countdown.start() command in the console, but that’s not required, you’ll see it in action in just a second.

How to use it

Okay, now that the technical prerequisites are done the rest of this guide are going to be much simpler I promise. At this point, you should have the direct URL of the Web Data Connector which you imported in the previous section.

Open up Tableau Desktop and either open an existing Workbook or create a new one with any data in it, it doesn’t really matter. Go to Dashboard view and add a new Web Page object with the URL pointing to the Web Data Connector. That’s it, I told you it’s going to be really simple. If you publish your Dashboard at this point, you’ll have the counter working with its default values (10 seconds timeout, 30px radius, green color palette, etc.) and if you are happy with these defaults then you can call it a day. If not, read along.

How to customize it

The beauty in the Tableau JavaScript API is that you can read the values of parameters or even subscribe to events when they are changing. Utilizing the power of this allows us to customize the counter in a user-friendly way without the need to dig into the HTML/JavaScript code of the Web Data Connector. The JavaScript API only works when the Tableau Dashboard is published to the web so unfortunately you won’t see the effect of the parameters in Tableau Desktop.

Without further ado, this is the list of parameters you can use to customize your counter:

  • autoRefresh_seconds: The number of seconds to count down from
    • Data type: integer
    • Default value: 10
  • autoRefresh_radius: The radius of the arc in pixels
    • Data type: Float
    • Default value: 30
  • autoRefresh_direction: The direction of the count down, clockwise (cw) or counterclockwise (ccw)
    • Data type: String
    • Default value: cw
  • autoRefresh_smooth: Should the timer be smooth or stepping once every second
    • Data type: Boolean
    • Default value: True
  • autoRefresh_fontSize: The font size, dynamically calculated if omitted (radius / 1.2)
    • Data type: Float
    • Default value: undefined, calculated from radius, eg. 30 / 1.2 = 25
  • autoRefresh_fontWeight: The font weight of the label
    • Data type: Integer
    • Default value: 700
  • autoRefresh_fontColor: The font color
    • Data type: String
    • Default value: #ffffff
  • autoRefresh_fontFamily: The font family
    • Data type: String
    • Default value: Sans-serif
  • autoRefresh_label: The label to display below the counter. Two labels are expected separated with a comma, one singular label for the second (ie. second or sec) and a plural label for anything more than that (ie. seconds or secs). If left blank or only a single label given no labels are going to be displayed.
    • Data type: String
    • Default value: second,seconds
  • autoRefresh_strokeWidth: The stroke width, dynamically calculated if omitted (radius / 4)
    • Data type: Float
    • Default value: undefined, calculated from radius, eg. 30 / 4 = 7.5
  • autoRefresh_strokeStyle: The color of the stroke
    • Data type: String
    • Default value: #477050
  • autoRefresh_fillStyle: The fill color
    • Data type: String
    • Default value: #8ac575

For any color related parameters, use the HEX color code starting with ‘#’ – there are dozens of color pickers online, search for one if in doubt.

So the flow of customizing the counter is as follows:

  1. Create a parameter in your Tableau Workbook for the one your are not happy with the default value, eg. autoRefresh_radius.
  2. Select the data type as denoted above and enter the new value you wish to use
  3. You have the option to either hide or display the parameter control in the dashboard. If displayed users of the Dashboard are going to be able to change the parameters on the fly and see the counter picking up the new settings instantly. This could come handy for playing with it until you find the options you want to stick with
  4. Note that in Tableau Desktop the counter will not pick up any of these parameters but when published to the web it will

Just to recap, only for the options you wish to override you’d need to create a parameter for, with the rest you don’t need to bother.

Technical tidbits

For the sake of completeness I would like to share a couple of things about how it’s all wired up under the hood, so you’d have a better understanding if you’d need to dig into the code.

When the Dashboard is launched with the Web Data Connector in it, the  <body onload="appApi.initAutoRefresh();"> (line #320) will be the one triggering the whole event chain, that function is defined starting from line #301. The countdown._drawCountdownShape  and countdown._drawCountdownLabel are only there so that in Tableau Desktop you’ll see at least something when the component is first added to the Dashboard, those lines can be safely removed if you are not worried about that.

Few lines below that, the getTableau function is what does the magic for us, so we can communicate with the JavaScript API of Tableau even within the Web Data Connector. Since our code is inside the Tableau’s own code within an iFrame, using the  parent JavaScript function, we can refer to the parent of our iFrame so using the parent.parent.tableau  (line #224) we can grab the object of the Tableau JavaScript API.

The initAutoRefresh()  does two more things apart from all this: subscribes to the event of parameter value changes ( onParamChange) and reads the current list of parameters ( getParameters). They both eventually will reach the processParam function which handles all parameters. Once all parameters are processed for the first time the countdown will be started at line #251.

One more interesting bit is at line #325. The onComplete() function of the countdown object is what defines what to do when the counter ticks. Ultimately what we want is to start a new countdown. The countdown.start() would simply do just that, but the problem with that is that it will start the new counter even before our Dashboard has finished reloading the data. That wouldn’t be too nice, imagine if you have a dashboard taking 8 seconds for example to refresh and you set the counter to 10 seconds – the Tableau Server would only have a 2 second break. Here is what I wanted instead: reload the data once the counter ticks -> wait for the Dashboard to finish reloading -> star a new counter. You would think (or hope at least) that the refreshDataAsync()  function of the JavaScript API would tell us when the refresh is done, but unfortunately it doesn’t (Tableau guys, if you are reading this, please make this function return a Promise like some other async function calls – cheers!).

How I ended up tackling this is that I used the MutationObserver so I can detect DOM changes. This MutationObserver is supported from IE11 and all other modern browser – Tableau 10.x also only supports IE11 and above from Microsoft’s browser so you should be good to go. If you need this solution for older Tableau versions and therefore need support for IE10 and earlier, you’ll need to tinker what this bit (or you might as well upgrade your Tableau Server to a newer version, right?). The MutationObserver will look for the loadingSpinner  element – as its name suggests that’s the spinner what you see when the dashboard is loading. Once it’s done, it will start the next countdown.

Got questions?

Feel free to ask

Norbert Ledenyi
Latest posts by Norbert Ledenyi (see all)

Related items

/ You may check this items as well

sync frelard

Tableau Extensions Addons Introduction: Synchronized Scrollbars

At this year’s Tableau Conference, I tried t...

Read more

Tableau External Services API: Adding Haskell Expressions as Calculations

We all have our own Tableau Conference habits.  M...

Read more
Scaling Tableau Image

Scaling out Tableau Extracts – Building a distributed, multi-node MPP Hyper Cluster

Tableau Hyper Database (“Extract”) is ...

Read more