This article is about combining vuejs and a chart framework/library plotly.js
I’ve been using this combination for about 6 months now and felt like writing about my solutions and ideas to combine these systems. Plotly.js has a implementation for react but not for angular or vuejs or similar frameworks.
This implementation is not really complicated or hard to understand but maybe it will be able to help people skip the struggles I had. In this article I make use of the reactive properties but I will write another article that uses a global eventBus to control the charts. This will give you more control on when to update and if updates went correctly.
In this article I will give some small code snippets and codepen.io examples. For the sake of simplicity I use a single js and html file instead of a fancy project structure.
The dependencies used in the codepen project are
* https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.css for simple styling
The first method we are building is using the buildin reactive properties of vuejs [vuejs docs]. with reactive properties I am referencing to the data in a component. I added a quick snippet of the data object I am using below.
Here you can see I create an object consisting of a uuid, an array of traces based on the plotly structure and a layout based on plotly as well. For now the layout is empty but this will change in the working implementation.
So for anyone who is familiar with vuejs you will know now that the chart object became a reactive property and can be watched to register changes. We will use this to create the dynamic chart. Now for the exciting part is creating a new vue component for the reactive chart.
To stay original we will call this component
reactive-chart and it will contain a prop that points to the before mentioned chart object and it will have a watcher on the chart object that tells the plot to update when the chart object changes. To make this work with the inside objects layout and traces we can use the
deep: true property in the watcher. Below I posted my current solution for a reactive chart.
As you can see it creates a template with an empty div which plotly can populate later. In the mounted life cycle we actually create the graph for the first time. We use the uuid as a ref attribute and fill the plot with the chart.traces and chart.layout. These are all based on the plotly models so plotly can use them without any changes.
Everything here looks nice and easy but there is one important method here that was quite undocumented and new during my experience with plotly.js and that is the
Plotly.react method. This method is able to detect changes in traces and layout and redraw the graph without any issue. The only things that are needed is creating a new traces array so it can detect it changed or explicitly tell plotly it changed by adding a
layout.datarevision property with preferably a timestamp as value [plotly.react documentation].
So we can choose to create a new array every time when you want to add or change data or we create the datarevision property. For the example implementation I went for adding the property but you can always tinker to what suits you best. So now we combine the app and the component and add some styling and interactions. Like adding random data to the first trace and changing the color of the trace and changing the x and y axis titles.
As you can see if you press the add data button it redraws the plot with the new data and changing the other properties also happen instantly. With just a few simple connections we create a fully dynamic plotly.js line chart. Of course this doesn’t only work for line charts you can apply this model to all the plotly charts as long as you adhere to there data models.
It’s an easy solution to quickly create dynamic charts with plotly.js and vuejs. But I am not sure how much resources plotly.react or deep reactive watchers take so I can not guarantee perfect performance with big datasets or multiple charts.
PS: This is my first article involving code and trying to present it a good way. So feel free to give me pointers and tips on how to improve on this article.