Section:

WebViewer in Salesforce - Frequently Asked Questions

What is WebViewer?

WebViewer is a pure client-side JavaScript library to annotate, view, and edit documents such as PDF, MS Office, Images, CAD, Video and more.

How can we use WebViewer in Salesforce?

We can embed WebViewer UI in Salesforce, contained in an iframe. WebViewer source code can be stored in Salesforce static resources, which allows for advanced document working client side without external dependencies and without your data ever leaving your Salesforce organization.

How do I optimize WebViewer for Salesforce

In Salesforce, we need to upload our WebViewer source files to static resources. Salesforce imposes a file size limit of 5MB for static resources, so we need to optimize our WebViewer worker files.

Since static resources are served from a different origin, we need to use a config.js file which runs in context of the WebViewer iframe. You can check out a sample config.js file.

What are the limitations of WebViewer in Salesforce?

Due to Salesforce's Governor Limits, we can only use Salesforce files within the allowed heap size (6MB/12MB async). WebViewer supports external file storage, from providers such as AWS, GCP, Azure, Dropbox and others - this allows for file support for sizes up to 2GB.

How to load WebViewerEntry Point with loadScript()?

After uploading your WebViewer worker files, make sure you use Salesforce's loadScript API to load the WebViewer entry point like so:

JavaScript

1//in your pdftronInstance.js LWC file
2renderedCallback() {
3 //your renderedCallback logic here...
4
5 var self = this;
6 if (this.uiInitialized) {
7 return; // prevent multiple initializations of WebViewer on each re-render
8 }
9 this.uiInitialized = true;
10
11 Promise.all([
12 loadScript(self, libUrl + '/webviewer.min.js'),
13 ])
14 .then(() => this.initUI())
15 .catch(console.error);
16}

How to instantiate WebViewer with Salesforce using a config file?

In Salesforce, the config file is used to set worker paths for our optimized WebViewer files and to access WebViewer objects and APIs. You can check out WebViewer fundamentals, which explains how WebViewer creates the UI app inside an iframe, so that Core namespaces and classes are encapsulated.

The iframe window and document object are still accessible through contentWindow and contentDocument, but it can still be tricky to run scripts or listen to events happening inside the iframe.

The config file gives you easy access to the Document, DocumentViewer and AnnotationManager objects (among others) which can allow you to make more complicated customizations.

To instantiate WebViewer with a config file you just need to set the config option in the WebViewer constructor. For example:

JavaScript

1//in your pdftronInstance.js LWC file
2const viewerElement = this.template.querySelector('div')
3
4const viewer = new WebViewer({
5 // snipped for brevity
6
7 config: myfilesUrl + this.config, // path to the config.js file in your static resources
8 // l: 'YOUR_LICENSE_KEY_HERE',
9}, viewerElement);

How do I setup worker paths in the config.js?

Before using WebViewer, you need to specify the worker paths for WebViewer with the below API calls. Keep in mind that some workers, such as office workers are only required if you want to include MS Office support and can be safely omitted if not required for your implementation.

JavaScript (v8.0+)

1// staticresource/config.js
2
3// office workers - optional
4window.Core.setOfficeWorkerPath(resourceURL + 'office')
5window.Core.setOfficeAsmPath(resourceURL + 'office_asm');
6window.Core.setOfficeResourcePath(resourceURL + 'office_resource');
7
8// legacy office workers - optional
9window.Core.setLegacyOfficeWorkerPath(resourceURL + 'office')
10window.Core.setLegacyOfficeAsmPath(resourceURL + 'office_asm');
11window.Core.setLegacyOfficeResourcePath(resourceURL + 'office_resource');
12
13// pdf workers
14window.Core.setPDFResourcePath(resourceURL + 'resource')
15if (custom.fullAPI) {
16 window.Core.setPDFWorkerPath(resourceURL + 'pdf_full')
17 window.Core.setPDFAsmPath(resourceURL + 'asm_full');
18} else {
19 window.Core.setPDFWorkerPath(resourceURL + 'pdf_lean')
20 window.Core.setPDFAsmPath(resourceURL + 'asm_lean');
21}
22
23// external 3rd party libraries
24window.Core.setExternalPath(resourceURL + 'external');

How do I pass custom data to WebViewer?

You can use a custom object and pass it to your WebViewer constructor to pass data from LWC to your config file upon initialization. To do this you can use the custom option in the WebViewer constructor. The property expects a string value. So for example to pass an object:

JavaScript (v8.0+)

1// LWC js file
2var myObj = {
3 libUrl: libUrl, // staticresources/lib.zip folder used for setting workerPaths
4 myfilesUrl: myfilesUrl,
5 fullAPI: this.fullAPI || false,
6 namespacePrefix: '', // pass a namespace prefix for managedpackages
7};
8 //var url = myfilesUrl + '/WVSF-Account-info-sample.pdf';
9
10const viewerElement = this.template.querySelector('div')
11 // eslint-disable-next-line no-unused-vars
12const viewer = new WebViewer({
13// snipped for brevity
14 custom: JSON.stringify(myObj),
15 // l: 'YOUR_LICENSE_KEY_HERE',
16 }, viewerElement);

Then inside the config file you access this data as follows:

JavaScript (v8.0+)

1instance.UI.addEventListener('viewerLoaded', () => {
2 const custom = JSON.parse(instance.UI.getCustomData());
3 console.log(custom.fullAPI); // outputs true or false
4});
5
6instance.UI.addEventListener('documentLoaded, () => {
7 const docViewer = instance.Core.documentViewer;
8 docViewer.setCurrentPage(custom.startPage);
9});

How do I use a config file when the path is on another domain

If you have the WebViewer path on a different domain than your app, then to protect against XSS attacks you will need to edit the lib/ui/configorigin.txt file to whitelist your app's domain(s). Add each domain on a separate line, for example:

sh

1http://localhost:3000
2https://example.com

Domains in this list will be allowed to have WebViewer specify config files that can be loaded.

Accessing outer page inside the iframe

If you want to access the outer page from inside the iframe (for Salesforce it is the parent LWC component), for example from code in your config file, you can access the parent window using window.parent. So if you defined an API that's loaded on your HTML page, you could access it from inside the iframe like window.parent.myApi.myFunction().

You could hook into WebViewer events and notify the parent LWC like so:

JavaScript

1//config.js
2window.addEventListener('viewerLoaded', () => {
3 // notify parent LWC that viewer has loaded and is ready for processing documents
4 window.parent.postMessage({ type: 'VIEWER_LOADED' }, window.origin);
5}

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales