Working with WebViewer APIs in Appian

Users may have needs not yet supported by the current Appian component. The WebViewer Appian component offers some high and low-level features of the WebViewer SDK. However, it only exposes a fraction of the SDK's capabilities, requiring mapping to reveal more. Rather than waiting for developers to enable these features, you can work directly with the APIs to create a solution that works for you.

This may be considered an advanced topic for those who may not know how to code, as this is considered high code territory. However, you can leverage our guides, code samples, and support to help in your journey and mastery!

Config files

WebViewer actually runs in an iframe where all the namespaces and APIs are accessible. To access these APIs, you can leverage a config file for WebViewer. Despite its name, it is actually a JavaScript file that is executed within the iframe.

You can upload this config file to Appian, and provide the document ID of the file to WebViewer.

Apryse Docs Image

Check out our repository with example config files for Appian.

Hooking into events

All of the events found in WebViewer are accessible. The most important being when the viewer is loaded as that is one of the earliest opportunities to setup WebViewer related settings or document preload actions (ex. fetching XFDF, notifying an external service, etc).

JavaScript (v8.0+)

1instance.UI.addEventListener(instance.UI.Events.VIEWER_LOADED, () => {
2 console.log("WebViewer Ready");
3 // Perform some preload actions or more WebViewer configuration
4 // Example - Disable UI elements on load. This is just an example and this functionality is actually a property of the component already.
5 // instance.UI.disableElements(['toggleNotesButton']);
6});

Other important events include documentLoaded and annotationsLoaded.

JavaScript (v8.0+)

1// Listening for when a document is loaded.
2// You can hook into this directly or when the viewer is ready.
3instance.UI.addEventListener(instance.UI.Events.DOCUMENT_LOADED, () => {
4 // Document is loaded and you can work with the document related APIs
5});

Passing data to the config file

In most cases, you want to provide some data from Appian to WebViewer to use for a particular use case. For example, you need to create a certain type of annotation at a specific location when a document is loaded. You can communicate this through the customData property of the component. It takes a JSON object which will be stringified and parsed, so only values and simple objects with values can be passed through this.

JavaScript (v8.0+)

1instance.UI.addEventListener(instance.UI.Events.VIEWER_LOADED, () => {
2 // Setup actions
3});
4
5instance.UI.addEventListener(instance.UI.Events.DOCUMENT_LOADED, () => {
6 // Get the Annotations namespace and the annotation manager from Core
7 const { annotationManager, Annotations } = instance.Core;
8 // Get the custom data assembled by WebViewer
9 const custom = JSON.parse(instance.UI.getCustomData());
10 // Get the custom data mapped to the property (provided by user)
11 const { customData } = custom;
12 // Create a rectangle annotation if user specified 'rect'
13 if (customData.type === "rect") {
14 const rectangleAnnotation = new Annotations.RectangleAnnotation({
15 PageNumber: 1,
16 X: 100,
17 Y: 100,
18 Width: 250,
19 Height: 250,
20 });
21 annotationManager.addAnnotation(rectangleAnnotation);
22 annotationManager.redrawAnnotation(rectangleAnnotation);
23 }
24});

customData object (WebViewer assembled)

It can be kind of confusing having two custom data objects, one embedded in the other. The parent custom data object is actually the object WebViewer assembles underneath with useful properties. Most of which are properties that were passed into the component at the very beginning. For example, if you had mentionableUsers set in the Appian component, you could find them here as well.

The customData property of that custom data object is the actual object that maps to the one provided to the component in Appian.

The following are some other properties found on the parent custom data object (subject to change):

  • appainDocId
  • automaticSemanticComparison
  • customData
  • customSubstituteFontUrl
  • darkMode
  • defaultLanguageCode
  • disabledElements
  • docAccessConnectedSystem
  • documentFolder
  • enableAnnotations
  • enableDocumentGeneration
  • enableExtractPagesToAppian
  • enableMeasurement
  • enableMultiTabMode
  • enableOfficeEditing
  • enablePdfEditing
  • enableRedaction
  • enableSemanticCompareMode
  • enableSignatureEncryption
  • enableSignatureRequests
  • enabledElements
  • loadAsPDF
  • mentionableUsers
  • notesInLeftPanel
  • searchTerm
  • serviceAPIKey
  • templateData
  • url
  • userDisplayName
  • watermarkOptions
  • xfdfAnnotationData
  • xfdfDocumentFolder

You can checkout the full list of the Appian component properties.

Passing data back to Appian (appianManager)

Now that we've looked at how to get data from Appian, we can take a look at how to send some data back to Appian. This is done through an object called the appianManager. This object manages the interaction between WebViewer and Appian through various APIs.

Triggering an event

To trigger events on the Appian side, you will need to call the saveValue function on the appianManager object. This function takes two parameters: the event name and the data to send back to Appian. The data can be any type of value, including objects and arrays. You can refer to our component properties to see what kind of events are available. However, triggering an existing event by yourself can cause unexpected behavior, so it's best to stick to the onCustomEvent event for your own custom events, and using a type property to differentiate between different events.

JavaScript (v8.0+)

1instance.UI.addEventListener(instance.UI.Events.DOCUMENT_LOADED, () => {
2 appianManager.saveValue('onCustomEvent', { type: 'myCustomEvent', data: 'some data' });
3});

Next steps

Look into what APIs exist within WebViewer to create a solution that works for you!

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales