Build a Word Cloud with a Lightning Web Component

Posted by

A few months ago at TralheaDX 2019, there was a portion of the conference where conference goers were given a problem to solve and they sat at a few tables and built out the solution. Naturally, I became obsessed with it and this was one of the exercises so I thought I would share the solution and walk through what I did to build it. The main takeaway from this post is to illustrate building to a canvas with a static resource. Others could attribute this to building with frameworks like ChartJS, etc. So here we go! First post of November 2019, woohoo!

First, let’s start with the host Github page for the word cloud resource. Here you can get access to the code needed to build your Lightning Web Component word cloud canvas. Let’s go over the business case, its pretty simple!

Build a Lightning Web Component that grabs twenty Accounts ordered by LastModifiedDate and show them in a canvas that builds the word cloud. After the accounts have been rendered in the word cloud, make them clickable and have the onclick event navigate to the corresponding record.

The first thing is to perform a simple query to grab your data. Remember that the cacheable setting is a great way to enhance performance so that the data stays on the client. If you are curious about the detailed functionality surrounding the cacheable property, you can navigate here to read more. It’s important to note that you should never perform DML in a method where you are applying the cacheable annotation.

public with sharing class ctrlGetAccounts {
    
    @AuraEnabled (cacheable=true)
    public static List<Account> getAccounts() {
        List<Account> accs = [SELECT Id, Name FROM Account ORDER BY LastModifiedDate LIMIT 20];
        return accs;
    }
}

Next, we can use the code from the github resource to create a static resource in Salesforce to reference from our web component. On a side note with Lightning Web Components, there are two recommended ways to reference a third party framework. One is a static resource that we will review today. The other is stored inside of a module that your web component imports. In my opinion, the second is best practice, however the first is what most Salesforce Developers are used to and the purpose of this blog is to help folks ramp up quickly and get to building really cool components for clients! Create your static resource and you’ll be good to continue. Next, we will discuss how to import your static resource into your Lightning Web Component. Here is the code below:

import { LightningElement} from 'lwc';
import cloud from '@salesforce/resourceUrl/wordCloud';
import { NavigationMixin } from 'lightning/navigation';
import { loadScript } from 'lightning/platformResourceLoader';
import getAccounts from '@salesforce/apex/ctrlGetAccounts.getAccounts';
export default class RecentAccounts extends NavigationMixin(LightningElement) {

    jsInitialized = false;
    
    navigate(Id) {
        console.log('what is id? ', Id);
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: Id,
                objectApiName: 'Account',
                actionName: 'view',
            },
        });
    }

    renderedCallback() {
        if (this.jsInitialized) {
            return;
        }
        this.jsInitialized = true;

        loadScript(this, cloud)
            .then(() => {
                var self = this;
                getAccounts()
                    .then(result => {
                        var List = new Array();

                        for (let i = 0; i < result.length; i++) {
                            List[i] = new Array ( result[i].Name, i, result[i].Id );
                        }

                        let options = {
                            'list' : List,
                            'fontFamily' : 'Arial',
                            'fontWeight' : 'normal',
                            'click' : function(item, dimension, event){
                                let Id = item[2];
                                self.navigate(Id);
                            }
                        }
                        window.WordCloud(this.template.querySelector('canvas.my_canvas'), options);
                    })
            })
            .catch(error => {
                this.error = error;
            });
    }
}

Let’s take a walk through the JS here. First, we create a property to check and see if the application was initialized. This is just because we only want to perform these actions if we truly need to. Next, all we do is build our data and construct what we need to send into the static resource code to do its thing. Sounds great but for the sake of being thorough, we can dig a little deeper. When we call getAccounts(), we return our results through a thenable method that gives us our data from the Apex controller. Per the documentation of the static resource, we need to loop over the results and construct the arrays within an array that have the Name of the Account, the iteration count, and the Id of the Account. After, we simply pre-construct our object with the List we just constructed and the callback method that acts as our onclick event with the selection of each Account. Once that is complete, we reference the canvas through the query selector and pass in our options object to construct the canvas. Here is the html below:

<template>
    <lightning-card title="Recently Accessed Accounts">
        <div class="slds-m-around_medium">
            <canvas class="my_canvas" lwc:dom="manual"></canvas>
        </div>
    </lightning-card>
</template>

Here is a quick screen share showing the overall functionality:

Its a relatively simple web component but a great way to get started with something simple and expand your application. Thank you for stopping by and let me know if you have any questions!

One comment

  1. Do you have an example ot the ‘proper’ module way to do it?
    I don’t see any of the Lightning export binding in the .js file from git.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s