Custom Dashboards with VueJS

Lately I have been working with one of my clients on some dashboard requirements for project/time-tracking data that they manage in Salesforce. Based on the desired visualization (a heatmap), as well as some more complex logic (comparing project data to averages from a subset of the projects), I concluded that the out-of-the-box reporting was not going to be adequate.

Solution

My first planned approach was to use a custom Lightning component for the project dashboard, and rely on a javascript charting library for the visualizations. I had done some prrof-of-concept work of this approach for simple dashboards a couple of years ago with some success. However, as I began prototyping, I found the javascript charting library running afoul of the Lightning Locker Service. I tried several of the popular libraries - AnyChart, amCharts, ChartJS (+ matrix report extension). Some worked partially, some not at all.

Seeking to steer clear of the Locker Service entirely, my next approach was to create an Aura component, and make use of the Lightning Container component. This component allows you to host a web app within an IFRAME in the Aura component - the hosted app has limited ability to interact with the surrounding container, but it is not impacted by the Locker Service. Salesforce provides an NPM module “lightning-container” that, among other things, allows your app to call Apex code.

So this was looking like a workable approach - develop an Apex controller class that would return the necessary Salesforce data, and build an app using the charting library of my choice to consume that data and render the dashboard.

The next question was which framework to use to develop the app - I had been learning VueJS for another client project, and it seemed a natural fit. It is lighter weight than some of the other javascript frameworks like React or Angular - any my needs were very simple.

Fastforwarding…. the Vue approach ended up very easy and smooth. I’ll share some tips and tricks I picked up along the way in a moment, but first a couple of screenshots of the dashboard:

Figure 1: The summary heatmap showing all projects

Figure 2: The drill-down from the heatmap, showing details for one project

Tips, Tricks, and Lessons

In no particular order, here are some tips and lessons from the process.

Apex Controller

Make your apex controller class global in scope, make the methods static, and include the @RemoteAction annotation.

Uploading your Vue Application to Salesforce

If your app is going to use an Apex controller to retrieve data, as in my dashboard example, you need to include a manifest.json file in the dist folder before you zip up the contents and upload to Salesforce as a static resource. Here is what the file needs to include:

{
    "landing-pages" : [
        {
            "path": "index.html",
            "apex-controller": "<controller class name>"
        }
    ]
}

Vue Paths

Update (or create if it does not exist) a file vue.config.js in the root of your Vue project. If it does not exist, all it needs to contain is the following:

module.exports = {
  publicPath: './'
}

If it does exist, you just need to update publicPath as above.

Styling with the Lightning Design System

You probably want your app to look native - thankfully it is not difficult to use the Lightning Design System in a Vue app to match the Lightning styling. First, install the module:

npm install @salesforce-ux/design-system

Then, include it in the style tags of your App.vue component:

<style>
@import url("../node_modules/@salesforce-ux/design-system/assets/styles/salesforce-lightning-design-system.min.css");
</style>

Then you can use the SLDS classes to style your app.

The Aura Component

This can be very simple:

<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
<lightning:container src="{!$Resource.<static resource name> + '/index.html'}"/>
</aura:component>  

Summary

My takeaway is that it is fairly easy to avoid Locker Service hassles and deploy high-quality dashboards with sophisticated visualizations in Salesforce, by using a Vue app and the Aura lightning:container component.

Please let me know if this post helped you, or if you have questions about my experience with Vue and Salesforce!