I am trying to build an embedded signing experience inside a Salesforce Experience Cloud Site from an LWC, and I tried to follow the documentation to build an LWC that can do the same. Here is the relevant LWC code -
import { LightningElement } from 'lwc';
import sendEnvelope from '@salesforce/apex/DocusignEmbeddedSigningController.sendEnvelope';
import getEmbeddedSigningUrl from '@salesforce/apex/DocusignEmbeddedSigningController.getEmbeddedSigningUrl';
import docusignjs from "@salesforce/resourceUrl/docusignjs";
import { loadScript } from "lightning/platformResourceLoader";
export default class DocusignEmbeddedSigning extends LightningElement {
template = '2d749f04-1bdb-4b70-9cef-64ab148c6ba0';
description = 'Embedded Signing';
renderedCallbackExecuted = false;
async renderedCallback() {
if (this.renderedCallbackExecuted) {
return;
}
this.renderedCallbackExecuted = true;
await Promise.all([
loadScript(this, docusignjs)
]);
let envelopeId = await sendEnvelope({template: this.template, description: this.description});
let signingUrl = await getEmbeddedSigningUrl({envId: envelopeId, url: window.location.href});
let docuSignObj = await window.DocuSign.loadDocuSign();
const signing = docuSignObj.signing({
url: signingUrl,
displayFormat: 'focused',
style: {
/** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
branding: {
primaryButton: {
/** Background color of primary button */
backgroundColor: '#333',
/** Text color of primary button */
color: '#fff',
}
},
/** High-level components we allow specific overrides for */
signingNavigationButton: {
finishText: 'You have finished the document! Hooray!',
position: 'bottom-center'
}
}
});
signing.on('ready', (event) => {
console.log('UI is rendered');
});
signing.on('sessionEnd', (event) => {
/** The event here denotes what caused the sessionEnd to trigger, such as signing_complete, ttl_expired etc../ **/
console.log('sessionend', event);
});
signing.mount(this.template.querySelector('.docusign-agreement-container'));
}
}
The problem is with the sigining.mount()
method. As per documentation (https://www.docusign.com/blog/developers/15-minutes-to-better-ux-enhancing-embedded-signing-focused-view, and https://developers.docusign.com/docs/esign-rest-api/how-to/request-signature-focused-view/), this method is supposed to receive an Id based selector.
But unfortunately, the LWC framework does not allow developers to provide their values in the ID attribute of HTML elements and will override them with dynamically generated values (which is why I attempted to use this.template.querySelector
to use a CSS based selector)
The get the following error with the above approach - [n.template.querySelector is not a function]
I then attempted this - signing.mount('.docusign-agreement-container');
, and now the error I get is this in the browser console - [DocuSign JS] Container element not found: ".docusign-agreement-container"
Question - Can the mount() method receive a different argument other than Id attributes? Otherwise, using the DocuSignJS library to embed signing experience within Salesforce Experience Cloud is not possible (or extremely difficult).
To anyone who is trying to do something similar, use LWCs in light mode to allow Docusign Library to work. Example below -
JS -
export default class PortalContractPage extends LightningElement {
static renderMode = "light";
connectedCallback() {
window.DocuSign.loadDocuSign()
.then((docusign) => {
this.showSpinner = false;
const signing = docusign.signing({
url: signUrl,
displayFormat:'default',
style: {
/** High-level variables that mirror our existing branding APIs. Reusing the branding name here for familiarity. */
branding: {
primaryButton: {
/** Background color of primary button */
backgroundColor: '#FA70A8',
/** Text color of primary button */
color: '#fff',
}
},
/** High-level components we allow specific overrides for */
signingNavigationButton: {
finishText: 'You have finished the document!',
position: 'bottom-center',
backgroundColor: '#FA70A8',
color: '#fff'
}
}
});
signing.mount(this.querySelector('.docusign-agreement'));
}
}
HTML -
<template lwc:render-mode="light">
<div class="docusign-agreement"></div>
</template>