Lightning Web Components using Lightning Out

Lightning Web Components (LWCs) are the new hot topic for Salesforce Developers.

But what if you are stuck in Classic?

I’ve been using Lightning Out with a Visualforce page to display what are now called Aura Components (the original Lightning Components).

But again, LWCs aren’t ready for Lightning Out.

Hmm…  But you can call LWCs from Aura Components.  So, you should be able to use Lightning Out with LWCs if you are willing to do a little setup and create a couple wrappers to get to the LWC.

Let’s dig in and have some fun with this.

This is going to live in Classic. Hence the need to find a different way to call LWCs. Here is our business case that we are solving for:

The sales team needs a list of contacts on their home page. Contacts should be in their division and assigned to the current active campaigns that are in progress so that they know which ones to call.

Here is what that means for us:

  • It’s going on the Home Page so it will be a Home Page Component calling a Visualforce page
  • The sales team division will come from User.Division
  • We will show a list of Contacts where Contact.MailingState matches User.Division
  • The Campaigns are current(StartDate-EndDate), active(IsActive), and in progress(Status = ‘In Progress’)

Sometimes it helps to visualize it:

When building in Salesforce it’s always a good idea to start building with the base, innermost item first. That way the item is already there, ready to be called from the item that is above it.

So here is our order of creation:

  • Apex Controller Test
    Yep, tests. Starting with tests helps you build good code among other things.
  • Apex Controller
    We will get our data here and prep it for display.
  • LWC
    Our view state and a Javascript controller
  • Aura App
    This one is simple, you’ll see.
  • Visualforce page
    Not too much here either. It will use Lightning and Javascript to call in the LWC through the Aura Component passing in a “name” variable along the way.

Apex Controller Test
CampaignContactsViewControllerTest

Just a quick test data setup and a couple of tests. There is a link in the Resources to the GitHub repo for these below.

Apex Controller
CampaignContactsViewController

There are a few things going on here:

  • Line 3 has the @AuraEnabled(cachable=true) annotation and we set the cachable=true so we can call it from the @wire decorator later. This also improves runtime performance.
  • Line 6 gets the User Division that is running the page
  • Line 8 takes the Division and removes blank spaces and splits the result of a comma-separated value into a List of Strings that we use in the SOQL below.
  • Lines 11 – 21 create the SOQL that we use to get the CampaignMembers where their MailingState matches the Divisions and the Campaigns that are active, in progress, and current.

We have the innermost part of our solution completed.

LWC
campaignContactView.html

This is the HTML file for the LWC, the beginning of the view state:

  • Line 2 has a title that uses a “name” variable that will be passed in from the Visualforce page.
  • Line 4 uses an if:true to detect if we have anything in the “contacts” variable and if we do then display the template.
  • Line 5 we display the number of contacts returned using the “contactLength” variable.
  • Lines 13- 20 uses the for:each to iterate over the “contacts” and display the information we pass back from the Javascript controller.
  • Line 23 is another if:true looking to display the “error” variable if we get one.

LWC
campaignContactView.js

This is where most of the magic happens… we connect to the Apex Controller and get data… manipulate and transform the data into a Javascript object for better control of the data returned to the view state… and insert it into the “contacts” variable:

  • Line 1 imports the base LightningElement and includes the decorators for api, track, and wire.
  • Line 2 imports the getCampaignMembers method from the CampaignContactsViewController Apex controller.
  • Lines 5-8 set up the variables using the decorators. “name” uses the @api decorator so we can pass it in from the Visualforce page.
  • Lines 10-33 uses the @wire decorator to call to the getMembers import and passes the result into the wiredGetMembers function.
  • Line 12 we set up an array of members that we’ll push each member into
  • Lines 13-28 takes the results and sets up a member object with the fields from the data returned for each campaignMember.
  • Line 21 builds out the link for the Contact so it is easy to use in the view state.
  • Lines 26-28 set the contacts, contactLength, and error variables.
  • That’s a lot of bullet points just to describe the code.

Aura Component
CampaignContactsViewContainerApp

This is our entry point into Lightning Out and our first wrapper container. You could use an Aura Component but the App is easiest for this implementation. This is the only file we need and it is only three lines.

The access parameter needs to be set to GLOBAL and it has to extend Lighting Out with the ltng:outApp.

The important line is the aura:dependency that sets the resource to our LWC campaignContactsView using the “c” namespace.

That was quick.

Visualforce
CampaignContactsViewContainer

Our second and final wrapper container. This visualforce page has an empty div that Javascript will populate with our LWC.

  • Line 2 “includeLightning” includes the Lightning Components for Visualforce JavaScript library, lightning.out.js, from the correct Salesforce domain. This allows us to call the Lightning Aura Component and access the LWC through it.
  • Line 4 is the empty div with an id parameter set so we can use it in the Javascript.
  • Line 8 inside a script tag calls $Lighting.use to connect the Aura Component.
  • Line 10 inside the function called for the Aura Component calls the $Lightning.createComponent with several parameters:
    • c:campaignContactsView : our LWC set as a dependency in the Aura app.
    • {name….} : variables that can be passed to the LWC in the @api decorator.
    • lightningContainer : the Id of the div tag that we are going to populate with the return from the LWC.
    • function : this allows us to run other things on success if we needed to. I just set a console log.
  • And that’s it. Pretty clean actually.

Home Page Component
CampaignContactsView

Since we are dealing with the Classic version of Salesforce we are using the Home Page to show the results. One way to do this is by using a Home Page Component that calls our CampaignContactsViewContainer visualforce page.

We just add that to the Home Page for the right users and we are all set.

How it looks

Wrap up

I hope this has been helpful. I’m looking forward to any feedback and improvements I can make. I’ve included some resources below that might be helpful including the complete code files.

Wait… Our PM just walked into the room… Oh, the business loves it. Awesome.

What, they want to change it? Why? (always ask why… usually several times)

They want sort options??? and they want to clear the list as they work through it?

It sounds like another post to me. See you in a few. Got to go write some updates.

Resources:

VS Code Setup with ForceCode

VS CodeVS Code is the new direction that Salesforce is going for its code editor of choice.  The focus is on DX and Scratch Orgs.

Salesforce has its own extensions for working in the Salesforce DX environment.  Here is a link to Salesforce’s directions for setting that up: https://developer.salesforce.com/tools/extension_vscode

And here is a Trailhead: https://trailhead.salesforce.com/en/content/learn/projects/quick-start-lightning-web-components/set-up-visual-studio-code

I added those but needed the ability to work directly with Sandboxes which the Salesforce extensions don’t have, yet.  The ForceCode extension has solutions for that and much more.  This is how I set up VS Code to use ForceCode.

ForceCode is an extension that allows you to make a connection to your Salesforce instance.  Sandboxes of course.  It also has some nice tools for working with your code like running tests and displaying test results and code coverage.

First go to the VS Code site and download the app.

Screen Shot 2018-06-17 at 3.59.13 AM

Run through the basic install process and start the app.

Once the app is open we will need to get the extension.  Look for the Extensions icon on the left menu of the app.  It looks like a square surrounding a square. Screen Shot 2018-06-17 at 4.03.55 AM

Then search for ForceCode and click on the Install button.  You will need to click the Reload button once it is done installing.  The picture is of an earlier version.  Current version is 3.16.0.  So just go with the latest.

Screen Shot 2018-06-17 at 4.14.55 AM

So far everything is going according to plan.  Let’s connect it to a Salesforce instance.

There are a couple of ways to do this.  Here is the easiest:

  • From the top menu, click View > Command Palette… or Cmd(Ctrl)-Shift-p
  • Search for forcecode and select the Create Project menu option
  • We are prompted with a request to select a folder…  or you can create one…  Click Create Project.
  • The prompt for “Select a saved org or login to a new one…” comes up.
  • Then we get to choose between Production / Developer, Sandbox / Test or Custom domain.
    Screen Shot 2018-06-17 at 4.46.02 AM
    If you are using this to access your Trailhead Playgrounds then use Developer.
  • Do you want to Automatically deploy/compile files on save or when use the ForceCode menu…  I usually select Yes.
  • Bingo! We should see a message in the bottom of the editor as it tries to connect and then a success message.
    Screen Shot 2018-06-17 at 4.53.04 AM
  • If you are creating a new org then it will open a browser and have you login to the Salesforce instance you want to work with prompting you if you want to allow access.  This is SSO sign on and doesn’t need a token!

Now let’s get some files from the server.

There are a couple of ways to get files from the server with ForceCode.

  • Open Salesforce File
    This allows you to get singular files
  • Retrieve Package/Matadata
    This allows you to get designated files in a managed package file or to get all the files from the org.

I went with the package.xml option.  I just created a quick package.xml file in the root of the src directory.

<?xml version=”1.0″ encoding=”UTF-8″?>
  <types>
    <members>*</members>
    <name>ApexClass</name>
  </types>
  <types>
    <members>*</members>
    <name>ApexComponent</name>
  </types>
  <types>
    <members>*</members>
    <name>ApexPage</name>
  </types>
  <types>
    <members>*</members>
    <name>ApexTestSuite</name>
  </types>
  <types>
    <members>*</members>
    <name>ApexTrigger</name>
  </types>
  <version>42.0</version>
</Package>

Go back to the ForceCode Menu and select Retrieve Package/Metadata > Retrieve by package.xml.  Just like that you should see the files located in the src directory.

Hope this was helpful.  Please send your comments below if I missed anything or if there is something particular you are looking for.

More to come on VS Code…

The Ongoing Journey

I’ve been programing for a long time.  Primarily front end web development with a healthy dose of mid-tier data work.

Almost four years ago I was introduced to Salesforce.  I was asked to bring some of my web applications into the Salesforce instance we were migrating to.  Little did I know how that would change the direction of my career.

I started out as a Developer, moved into Admin, and now I’m back to Developing with an Admin perspective.

This is going to be a place for me to catalog some of the best practice options I find.  I hope they are useful to others as well.

Thanks for joining the journey!

Mark