Ever wondered that it would be pretty interesting if we were able to call that well contained but complex integration procedure reused in x other OmniScripts into a Lightning Web Component(LWC).
Imagine the declarative nature of the Integration procedure – no apex, no AuraEnabled decorated methods, no test classes - with the flexibility of the LWC would make prototyping blazing fast.
Since Winter ’20 release Vlocity introduced the new LWC OmniScript Action Framework that allows to make remote calls using the framework methods by simply importing the Common Action Utility class.
Let’s see how we can leverage the LWC OmniScript Action Framework to integrate an external service to shorten URLs through an Integration Procedure(IP) into a standalone LWC embedded in an Omniscript(OS).
Take note that the same result could be achieved with a IP directly called in a OS Step with two input fields to hold the URLs, the POC that we’ll build just proves the point and you can use it on more complex flows whereby you need to call IPs in LWC, for instance when overriding OS components.
Lightning Web Component
Our first step is to create the custom LWC that will be responsible for accepting the URL inputted by the user, call the IP, receive and display the response.
1. The .js-meta.xml configuration
To expose the component to the app builder the <isExposed> element must be set to true.
The namespace of the Vlocity package must also be set in the <runtimeNamespace> metadata element.
You can quickly check the namespace of the Vlocity package you’re running in the Installed Packages on Salesforce Setup. In this example I’ll use the vlocity_cmt - the namespace for the Vlocity Communications, Media and Energy managed package.
The xml file should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>50.0</apiVersion>
<isExposed>true</isExposed>
<runtimeNamespace>vlocity_cmt</runtimeNamespace>
</LightningComponentBundle>
2. The .html file
For the html we’ll create a container using the <lightning-card > that will group two input fields <lightning-input> of the type url, so we can have a nice out of the box URL validation. The input field with the iurl class will receive the user input and the field with the ourl class will output the url from the IP through the shortURL reactive property:
<template>
<lightning-card title="URL Shortener" icon-name="standard:link">
<lightning-input class="iurl" type="url" name="inputURL" placeholder="Enter valid URL here..."></lightning-input>
<lightning-input class="ourl" type="url" name="outputURL" value={shortURL}></lightning-input>
</lightning-card>
</template>
<template>
<lightning-card title="URL Shortener" icon-name="standard:link">
<lightning-input class="iurl" type="url" name="inputURL" placeholder="Enter valid URL here..."></lightning-input>
<lightning-button variant="brand" label="Shorten" onclick={handleShortenURL}></lightning-button>
<lightning-input class="ourl" type="url" name="outputURL" value={shortURL}></lightning-input>
<lightning-button icon-name="utility:copy_to_clipboard" variant="brand" label="Copy" onclick={handleCopy}></lightning-button>
</lightning-card>
</template>
Since the field that holds the shortened URL will be necessary only after the user triggered the action we will add a conditional rendering <div if:true={isSuccess}… so it only displays on a successful shortening of the URL .
After arranging and adding some styling the final html look like this:
<template>
<lightning-card title="URL Shortener" icon-name="standard:link">
<div class="slds-grid slds-grid_vertical-align-end slds-gutters">
<div class="slds-col slds-size_2-of-3">
<lightning-input class="iurl" type="url" name="inputURL" placeholder="Enter valid URL here..."></lightning-input>
</div>
<div class="slds-col slds-size_1-of-3">
<lightning-button variant="brand" label="Shorten" onclick={handleShortenURL}></lightning-button>
</div>
</div>
<div if:true={isSuccess} class="slds-grid slds-grid_vertical-align-end slds-gutters slds-p-top_medium">
<div class="slds-col slds-size_2-of-3">
<lightning-input class="ourl" type="url" name="outputURL" value={shortURL}></lightning-input>
</div>
<div class="slds-col slds-size_1-of-3">
<lightning-button icon-name="utility:copy_to_clipboard" variant="brand" label="Copy" onclick={handleCopy}></lightning-button>
</div>
</div>
</lightning-card>
</template>
3. The javascript file
To take advantage of the Vlocity LWC OmniScript Action Framework we will have to import the Vlocity OmniscriptActionCommonUtil utility class from the Vlocity omniscriptActionUtils. This class will give us access to the executeAction method where, in the parameters, we can define the Integration Procedure that will be called, the input to send, and which options to switch on, such as run as future, queueable and chainable. The executeAction will start the call to the IP and return a promise with a result property that contains the response from the IP and an Boolean error property that indicates the status of the invocation. From the result property we get the URL shortened and an Boolean indicative of the successful http action call and assign them to the reactive fields shortURL and isSuccess that upon update will re-render in the html template surfacing the shortened URL and the copy button in the UI.
Let’s first import the OmniscriptActionCommonUtil and instantiate it on the connectedCallback() so we have the methods available whenever we request them.
We will also use the imported getNamespaceDotNotation() from the omniscriptInternalUtils so we can retrieve the Vlocity Package namespace:
import { LightningElement } from "lwc";
import { getNamespaceDotNotation } from "vlocity_cmt/omniscriptInternalUtils";
import { OmniscriptActionCommonUtil } from "vlocity_cmt/omniscriptActionUtils";
export default class UrlShortener extends LightningElement {
_actionUtil;
_ns = getNamespaceDotNotation();
connectedCallback() {
this._actionUtil = new OmniscriptActionCommonUtil();
}
}
import { LightningElement } from "lwc";
import { getNamespaceDotNotation } from "vlocity_cmt/omniscriptInternalUtils";
import { OmniscriptActionCommonUtil } from "vlocity_cmt/omniscriptActionUtils";
export default class UrlShortener extends LightningElement {
_actionUtil;
_ns = getNamespaceDotNotation();
connectedCallback() {
this._actionUtil = new OmniscriptActionCommonUtil();
}
handleShortenURL() {
let input = this.template.querySelector(".iurl").value;
this.IPInput = {
url: input
};
const options = {};
const params = {
input: JSON.stringify(this.IPInput),
sClassName: `${this._ns}IntegrationProcedureService`,
sMethodName: "integration_URLShortenerIntegration",
options: JSON.stringify(options)
};
}
}
Finally we can call the executeAction and pass the parameters we set before. After it's executed it will return a promise with the response from the IP, when done it’s the time to update our fields isSuccess and shortURL so that the data displays on the screen.
Note that executeAction receives 5 arguments being, the parameters as an object, a string with the queueable Id, the component, an extra payload and some other vlocity params, in most cases the parameters and the component are sufficient and we can safely nullify all other arguments:
import { LightningElement } from "lwc";
import { getNamespaceDotNotation } from "vlocity_cmt/omniscriptInternalUtils";
import { OmniscriptActionCommonUtil } from "vlocity_cmt/omniscriptActionUtils";
export default class UrlShortener extends LightningElement {
shortURL;
isSuccess;
_actionUtil;
_ns = getNamespaceDotNotation();
/* ... */
handleShortenURL() {
/* ... */
this._actionUtil
.executeAction(params, null, this, null, null)
.then((response) => {
this.shortURL = response.result.IPResult.response;
this.isSuccess = response.result.IPResult.isSuccess;
})
.catch((error) => {
console.error(error, "ERROR");
});
}
}
As a bonus I’ve added a copy button so the user can quickly copy the shortened link to the clipboard.
The handleCopy() will create a short lived document that will hold the link string. Using the execCommand("copy") we will execute the copy command so the selected input element of the document is copied to the clipboard:
import { LightningElement } from "lwc";
import { getNamespaceDotNotation } from "vlocity_cmt/omniscriptInternalUtils";
import { OmniscriptActionCommonUtil } from "vlocity_cmt/omniscriptActionUtils";
export default class UrlShortener extends LightningElement {
/* ... */
handleCopy() {
var tempInput = document.createElement("input");
tempInput.setAttribute("value", this.shortURL);
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
}
}
Our final version of the javascript file will look like this:
import { LightningElement } from "lwc";
import { getNamespaceDotNotation } from "vlocity_cmt/omniscriptInternalUtils";
import { OmniscriptActionCommonUtil } from "vlocity_cmt/omniscriptActionUtils";
export default class UrlShortener extends LightningElement {
shortURL;
isSuccess;
_actionUtil;
_ns = getNamespaceDotNotation();
connectedCallback() {
this._actionUtil = new OmniscriptActionCommonUtil();
}
handleShortenURL() {
let input = this.template.querySelector(".iurl").value;
this.IPInput = {
url: input
};
const options = {};
const params = {
input: JSON.stringify(this.IPInput),
sClassName: `${this._ns}IntegrationProcedureService`,
sMethodName: "integration_URLShortenerIntegration",
options: JSON.stringify(options)
};
this._actionUtil
.executeAction(params, null, this, null, null)
.then((response) => {
this.shortURL = response.result.IPResult.response;
this.isSuccess = response.result.IPResult.isSuccess;
})
.catch((error) => {
console.error(error, "ERROR");
});
}
handleCopy() {
var tempInput = document.createElement("input");
tempInput.setAttribute("value", this.shortURL);
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
}
}
Integration Procedure We will delegate the process to shorten the URLs to the cleanuri.com API services that we’ll access through an HTTP call action. Besides returning the shortened URL, the response from cleanuri.com will be screened for errors and a isSuccess Boolean node returned to allow conditionally render the URL and the copy button on the LWC UI.
Omniscript Finally we will wrap our LWC inside an Omniscript through a standalone Custom LWC. This way we can leverage the Vlocity packages and utils we saw until now.
Flexipage We are left only with the configuration of the display of the LWC Omniscript on a record flexipage.
|
A reprodução deste vídeo não está disponível neste momento
Conclusion
Although being a simple component we built, we can see the benefits of using the OmniScript Action Framework to make remote calls to Integration Procedures leveraging its declarative programming for fast implementation of backend processes coupled with LWC to build flexible web components tailored to meet customers UI/UX expectations.