This is the second of a two-part article. If you haven’t done it yet, I’d recommend you checking the first one before proceeding. As a quick recap, VA and third-party visualizations communicate with each other through messages. As a developer of the third-party visualization, you must understand how those messages are formatted, and how to process them. This is what we are going to be discussing, in addition to best practices and examples.
A closer look at the messages
As said before, there are three different types of messages, all in JSON format:
From VA to third-party visualization (received from VA)
Data message - contains mainly data and columns metadata, among other information
From third-party visualization to VA (sent to VA)
Selection message - used to filter or brush other VA objects
Instructional message - text to be displayed in the DDC object
Data message received from VA
The message received from VA comes as event.data. This JSON object has a few elements, such as version, resultName, rowCount, data, columns, and more.
01-Structure of the message received from VA
The data itself is provided as a two-dimensional array of rows and columns, like a table, and referenced as “data” in the message. For example:
data.data[0] is the first row of data
data.data[0][0] is the first column of the first row of data
Numeric data is not formatted. For example: $ 6,543,621 comes as 6543621. But dates and datetimes are formatted as strings, such as “Jan.” The actual format being used is provided as a column metadata. As a developer of the third-party visualization, you must use that information to make the necessary transformations in the data prior to visualizing it.
Data points (rows) of that table can be selected (brushed). Those selections are informed as an additional (optional) numeric column. Any value greater than 0 in this column indicates the row is being selected.
02-Data table received from VA and its representation as a two-dimensional array
In the example above, if the last column is indicating selection, then the second row is being selected. Column metadata is responsible for telling if the column is indicating selection or not. Again, it’s the developer’s responsibility to interpret the information and make the appropriate selections in the third-party visualization.
Columns metadata is referenced as “columns” in the message and represented as an array of objects, where each object contains information or attributes about a column, such as name, label, type, format, usage, aggregation, etc. Except for name, label, and type, the other attributes are optional or vary according to the type of the column. If a column metadata contains the attribute called “usage” and it is set to “brush,” then that a column is not a real data column, but it’s used to indicate selection. There must be zero or one of those columns.
Another important piece of information found in the message received from VA is the “resultName.” This attribute is used when sending messages back to VA. There are other less common attributes that are not covered here, and additional information can be found in Programming Considerations for Data-Driven Visualizations.
Putting everything together, a typical message received from VA would look like this:
03-Example of typical message received from VA
Selection and instructional messages sent to VA
Both selection and instructional messages sent to VA are very simple JSON structures.
The selection message contains only two attributes:
resultName - came in message received from VA
selections - array of objects representing the selected row numbers
The instructional message contains only two attributes as well:
resultName - came in message received from VA
message - the text to be displayed
04-Examples of messages sent to VA
Receiving and sending messages (connecting the dots)
To receive and send the messages discussed above, you must write code - yes, coding time has finally arrived, if you were wondering.
The following snippet of code is an example of an event listener that can be used to receive messages from VA. You can store it in a library and make it available as a function call for reusability as well as to hide the details of the implementation, but this is essentially what you need to do to get the message from VA.
05-Example of event listener to receive messages from VA
To send a message back to VA you just need to send a post message, like in the snippet below. The message passed as parameter to the sendMessage function is a JSON object formatted as either a selection or an instructional message, as seen before:
06-Example of code to send messages to VA
Remember that a selection message should be sent when the report consumer interacts with the third-party visualization by clicking somewhere in the chart for example. This interaction is usually captured by an event and you must define the listener and handler for this event. The concept is the same as discussed here for receiving messages from VA, but the implementation is most likely different. Refer to your third-party visualization documentation to know more about the events it supports.
Handling messages received from VA
In the example above, the function eventHandlerFromVA is being called whenever a new message arrives. You are free to process those messages the way you want, but as a best practice, after integrating a few third-party visualizations with VA, these are some the steps that you should consider for your event handler function:
Validate the message structure. Check for elements you know you will be using, such as “resultName,” “data,” and “columns.” Are they present? Do they have values? Check them once and forget about it. This is not really necessary if you trust that VA will always send you a well-formed message, but it doesn’t hurt to be safe.
Store the received message, or at least the content of “resultName” in a global variable for later use. You will need it.
Extract information about selections. As explained before, selected rows are informed in an additional column that isn’t a data column. Identifying and storing those selections in a separate structure will allow you to eliminate that additional “brush” column and keep only real data from this point on.
Validate assigned roles. As a generic object, the DDC object doesn’t know upfront what data roles must be assigned to the object in VA, their types, or sequence. It’s up to you as the developer to check that by examining the columns metadata and sending an instructional message to inform the user if something is wrong or missing. For example, a Google calendar chart expects 2 columns, in this order: date and number. In some cases, the chart may accept optional roles, and you should take that into consideration as well if you decide to support them.
Process formats (especially numeric and date columns) according to columns metadata and transform data as required by target chart. For example, Google Charts use the input data as a DataTable object, not as an array. Google Charts also manipulate dates as Date objects, not as strings as received in the message. Other third-party visualizations have their own requirements.
Refresh the chart based on the new data and selections. This is where you call the function that draws the third-party chart.
The code template below summarizes all those steps:
07-Template for event handler of messages received from VA
Again, this is just a suggestion. The order of those steps may be slightly changed, if you are careful enough. For example, validating assigned roles before extracting information about selections is possible, as long as you remember to ignore “brush” columns. I’ve also seen implementations where the developer (more advanced than me) decided to transform the two-dimensional array of data into a DataTable object as one of the first steps. DataTable offers a set of methods that operate on tables, instead of having to deal with arrays, indexes, and JSON objects explicitly throughout the rest of the code. I like that! DataTable is also how Google Charts expect input tables to be, so it makes a lot of sense to transform the data array into a DataTable right from the start.
Bringing everything together
So far you have been introduced to the key elements that you should be implementing to add a third-party visualization into VA. All that JavaScript code lives in an HTML file that must be deployed in a Web server, so you can refer to it as an URL within a VA DDC object. The HTML file itself is quite simple in the body of the HTML you only need a div tag. You should also think about the CSS elements to add to the style in the HTML file. Again, there is no one size fits all approach, but for the charts I’ve worked with, I’ve found that the one below, with a few tweaks sometimes, is a good starting point for a clean look:
08-HTML file template with CSS
Is this all? Certainly not. I’m sure you will find other things to add to your third-party visualization to make it shine, after all, the code is yours. One thing for sure will take the implementation a step further: resizing and/or scrollbars. Being able to resize and/or add scrollbars when necessary to your chart, depending on the size of the browser window and/or other factors, might be something to think about. I’ve also found useful to embed a small sample data in the code, so that a sample chart can be displayed, like a template, even before data gets assigned to the roles (see figure 07 in part 1 of 2 of this article).
Once the HTML file is ready and hosted in a Web Server, just add its URL under the DDC object’s Options pane.
09-Setting Data-Driven Content URL in DDC object’s Options pane
As the number of third-party visualizations that you develop and are ready for DDC object increases, you can go to Edit administration settings in the top right menu and map their URLs. This allows quick access to third-party visualization via a dropdown in the DDC object’s Options pane:
10-Data-Driven Content URL mappings
Below is an example of a VA report with Google OrgChart. The List Table and DDC objects are connected by a selection (brush) action, so clicking in one object highlights the other:
11-Example of Data-Driven Content object with Google OrgChart embedded in VA report
Observe that we normally think about visualizations when dealing with Data-Driven Content objects, but it’s not restricted to this usage only. I’ve seen implementations that utilized DDC object to pass data and communicate with other applications and I’m sure people will come up with other interesting ideas. The sky is the limit!
Full examples of third-party visualizations can be found in GitHub. There isn’t much there yet, but the idea is to get this library started so we all can contribute and benefit from new visualizations and samples. If you contribute with new visualizations, please let us know by leaving a note in the comments section. My Google OrgChart example should be there soon and I hope to see yours too!
Download the Files (GitHub)
Additional resources on Data-Driven Content:
Documentation: Programming Considerations for Data-Driven Visualizations
Community article: Data-Driven Content: leveraging third-party visualizations in SAS Visual Analytics (part 1 of 2) by SAS' Renato Luppi
Community article: Leverage a Google 3D-PieChart within VA using the Data-Driven Content Object by SAS’ Meera Venkataramani
SAS Global Forum paper: Create Awesomeness: Use Custom Visualization to Extend SAS Visual Analytics to Get the Results You Need by SAS’ Robby Powell and Renato Luppi
... View more