Tableau Dashboards are great for a lot of things; however, one need I hear often is the ability to add notations to dashboards. You can obviously add notations inside Tableau Desktop, but in an Enterprise level dashboard, there are many issues with this approach.
Any user annotating your dashboard would need access to edit the Tableau file. Sometimes (usually), these users are not as familiar with Tableau and may find this approach daunting. Even when users are properly trained on annotating the dashboards (and you are confident that they will not destroy anything), they will need to publish a new version of the dashboard every time a new annotation is needed.
In enterprise environments, collaboration drives adoption. I’ve seen teams pull dashboards into PowerPoint and add notations there. Wouldn’t it be better (and simpler) to simply give these same teams tools to add notations inline?
Luckily, with a little JavaScript API magic, there is another way to leave notations on dashboard points! Unlike traditional annotations, these notes come into the data as fields and can be formatted and customized as much as you’d like.
In our example, I’m using a simple comment box storing the comment on the month. Since this is web-based, you could add as much functionality as you’d like. For example, you could store the username of the commenter, a “category” to change colors in the tooltip or even something as simple as a “like”/”dislike.”
How It’s Done
I’ve attached the source code for this project to this post. Basically, at a high level, we used the JavaScript API to catch mark selections and then PHP to store the mark in a database accessible to Tableau. Feel free to dive into the code if you’d rather skip ahead!
In building out the setup, first we need a dashboard. I used Superstore as a base, but you could obviously use whatever data you want.
Next, I setup a table to hold our comments. For my table, I simply need a key to store the “Month” and a field for the “Comment” itself. If you wanted to store more information, such as a username, you could add an additional field to this table.
After completing the table, I created a new live connection in the Superstore-based workbook to the new comment table. Use a live connection here so that you get the latest comments as they are entered.
Now, let’s dive into the JavaScript side! To start, I created a hidden modal window waiting for the user to click a mark. I used the MARKS_SELECTION event to show this modal when the user clicks a mark:
/** * Instantiate our vizualization. */ $(function() { $('.detailBox').hide(); $('.hiddenBg').hide(); var url = 'https://sampleServerUrl/views/SuperStoreSalesVProfit/SuperStoreSales'; var vizOptions = { showTabs : true, hideToolbar : true, width : "420px", height : "420px" }; currentViz = new tableauSoftware.Viz(document.getElementById('viz'), url, vizOptions); currentViz.addEventListener(tableauSoftware.TableauEventName.MARKS_SELECTION, onMarkSelect); }); /** * Catches the tableau event fired when a filter is changed. */ function onMarkSelect(e) { e.getMarksAsync().then(function (marks) { for (var i = 0; i < marks.length; i++) { var pairs = marks[i].getPairs(); for (var j = 0; j < pairs.length; j++) { if (pairs[j].fieldName == 'MONTH(Order Date)') { selectedMonth = pairs[j].formattedValue; annotateMonth(); return; } } } }); }
When the user clicks the save link, the comment data is passed through Ajax to a PHP script that saves the content to the database. When the Ajax call is complete, I used the JavaScript API to reset the marks and refresh the dashboard’s data. This allows the user to see their comment as soon as they post it.
/** * Saves the annotation to the database */ function saveAnnotation() { $.ajax({ url : "add_comment.php", data : { 'month' : selectedMonth, 'comment' : $('#notes').val() } }).done(function() { var sheets = currentViz.getWorkbook().getActiveSheet().getWorksheets(); for (var j = 0; j < sheets.length; j++) { sheets[j].clearSelectedMarksAsync(); } currentViz.refreshDataAsync(); $('#notes').val(''); }); hideAnnotation(); }
And there you have it – inline notations in Tableau without having to edit the Tableau file itself! This example is fairly simplistic, but it can easily be expanded to fit many different needs. Using the JavaScript API, customization is only limited by your imagination!