Some test text!

Search
Hamburger Icon

Web / Guides / Migrating to Modular UI

Migrating to V11 Modular UI

Overview and Philosophy

In WebViewer 11, the default UI has been changed to the new Modular UI . This new UI is more flexible and allows for more customization.

The previous UI is still available and can be used by setting the ui option to legacy in the WebViewer constructor.

WebViewerConstructor(
  {
    path: '/path/to/your/webviewer',
    initialDoc: '/path/to/your/document.pdf',
    ui: 'legacy',
  },
  document.getElementById('viewer')
).then(instance => {

});

With the Modular UI, you can now easily customize your UI by adding and remove components, or alternatively building your own UI from scratch.

One of the main changes in the Modular UI is that you are able to import only the necessary components for your UI, instead of loading them all and disabling the ones you don't need.

Diagram of Modular UI

This can be done using a JSON config file in which you can define the Modular Components (ie. Buttons, Ribbon Items, Grouped Items), Modular Headers , Flyouts , and Panels that you want to use and then importing it into the UI.

Webviewer.WebComponent(
  {
    path: '/path/to/your/webviewer',
    initialDoc: '/path/to/your/document.pdf',
  },
  viewerElement
).then((instance) => {
  const configUI = {
    "modularComponents": {
      "myButton": {
        "type": "customButton",
        "dataElement": "myButton",
        "label": "My Button",
        "onClick": "alertClick"
      },
      "flyoutToggle": {
        "type": "toggleButton",
        "img": "ic-hamburger-menu",
        "dataElement": "flyoutToggle",
        "toggleElement": "myFlyout"
      },
      "flyoutFirstButton": {
        "type": "customButton",
        "dataElement": "flyoutFirstButton",
        "label": "Flyout First Button",
        "children": [
          "flyoutSecondButton"
        ]
      },
      "flyoutSecondButton": {
        "type": "customButton",
        "dataElement": "flyoutSecondButton",
        "label": "Flyout Second Button",
        "onClick": "flyoutSecondButtonOnClick"
      },
      "searchPanelToggle": {
        "type": "toggleButton",
        "img": "icon-header-search",
        "dataElement": "searchPanelToggle",
        "toggleElement": "myPanel"
      }
    },
    "modularHeaders": {
      "myHeader": {
        "dataElement": "myHeader",
        "placement": "top",
        "items": [
          "flyoutToggle",
          "myButton",
          "searchPanelToggle"
        ]
      }
    },
    "panels": {
      "myPanel": {
        "dataElement": "myPanel",
        "location": "left",
        "render": "searchPanel"
      }
    },
    "flyouts": {
      "myFlyout": {
        "dataElement": "myFlyout",
        "items": [
          "flyoutFirstButton"
        ]
      }
    }
  };

  const functionMap = {
    'alertClick': () => alert('Alert triggered!'),
    'flyoutSecondButtonOnClick': () => {
      console.log('Second Item clicked!');
    },
  };

  instance.UI.importModularComponents(configUI, functionMap);
});

In the example above, a functionMap is also used to define the onClick functions for the buttons.

This new way of customizing the WebViewer UI is more flexible and allows for more control over the UI components that are used.

Along with importing UI configs, there is also the new ability to export a UI config using the UI.exportModularComponents API. This can be useful if you want to save a UI configuration to use in another instance of WebViewer.

const exportedUI = instance.UI.exportModularComponents();
console.log(exportedUI);

Modular UI Equivalents for Existing APIs

Because of the change to the new UI, there are now different APIs for interacting with and customizing the WebViewer UI.

The table below summarizes how a few of the existing APIs have changed in the Modular UI:

Existing APIMatching API in Modular UI
setToolBarGroup()
New Modular API, also has a matching getter to see which ribbon item is currently active, getActiveRibbonItem()
setHeaderItems()
New Modular APIs to return a header object, which has methods on it to set items and properties. These update dynamically in the UI. See ModularHeader Class.
setActiveHeaderGroup()
Changing headers can be done simply by adding a new header or by changing out the entire list of headers with a new one. See ModularHeader Class.
setCustomPanel()
  • addPanel - allows users to add a standalone panel to the left or right, using custom code or the existing preset panels
  • getPanels - returns all panels
  • setPanels - sets all panels

The legacy API only allows you to add a tab to the left panel. With the new APIs, you can set custom or existing panels to the left or right. If you want to add a tab to a tabbed panel (i.e., the default leftPanel), you can get the TabPanel with getPanels and add a tab to its `panelsList`.
MenuOverlay Class
This class implements three methods to customize the hamburger menu:
  • getItems
  • add
  • update

This uses the new Flyout class, which has the following methods and properties:
  • setItems
  • items property
  • Option to instantiate with an array of items

All existing legacy methods work with new Flyout.
PageManipulation Overlay
Has access to methods to update and set the items in the page manipulation overlay (opened via thumbnails)
  • getItems
  • add
  • update

Also has two methods to customize onClick behaviors:
  • disableOpeningByRightClick
  • enableOpeningByRightClick

These APIs control if we can open this overlay with a right click.
PageManipulation Overlay is now a Flyout with the same methods as the legacy overlay. It also has access to all methods and properties of the new Flyout class.

All existing legacy methods work with new Flyout.

Examples

Below are some examples of how to use the new Modular UI APIs to customize the UI.

Changing Header Items

Before

You would use the API UI.setHeaderItems to change the header items or the API UI.setActiveHeaderGroup to manipulate the header.

After

There are now different ways that headers can be used in the Modular UI. You can now have multiple headers in different places in your UI. As such, there are now getters such as UI.getModularHeader and UI.getModularHeaderList which return header object that include methods to set items and properties. When headers are changed they will be updated dynamically in the UI.

You can also add new headers or change the current list of headers with the APIs UI.addModularHeaders and UI.setModularHeaders.

The following example shows how to change the items in a header:

const header = instance.UI.getModularHeader('default-top-header');
// replace all items in the default top header with a new button
header.setItems([{
  type: 'customButton',
  dataElement: 'testButton',
  label: 'My Button',
  title: 'My Button',
  onClick: () => {
    console.log('Button clicked');
  }
}]);

Editing the Main Menu

Before

You would use the settingsMenuOverlay interface to customize the hamburger menu.

After

You can now use the new Flyout class, which has the setItems method that you can use to change the items in the flyout. To find the flyout you want to change, you can use the getFlyout method.

instance.UI.Flyouts.getFlyout('MainMenuFlyout').setItems([
  {
    type: 'customButton',
    className:"row",
    img: 'icon-header-print-line',
    onClick: () => {
      alert('Hello world!');
    },
    dataElement: 'alertButton',
    label:'test button',
    role:"option"
  },
  {
    type: 'customButton',
    className:"row",
    img: 'icon-header-print-line',
    onClick: () => {
      alert('Hello world!');
    },
    dataElement: 'alertButton2',
    label:'test button 2',
    role:"option"
  },
]);

Moving Items into a Header

Before

In order to move items from the Main Menu to the header, it would require a lot of custom code. You would need to create a custom button for each one that you wanted to move and add that button to the header. Creating the custom button would also mean finding the APIs to call from the button's onClick method and whichever icon you wanted to use.

After

With the new Modular UI, you can easily move items from the main menu to the header by using preset buttons along with the setItems methods, shown above, for the main menu and header.

// Download button from the Main Menu
const downloadButton = new instance.UI.Components.PresetButton({
  buttonType: 'downloadButton',
  dataElement: 'presetButton-download'
});

// Save As button from the Main Menu
const saveAsButton = new instance.UI.Components.PresetButton({
  buttonType: 'saveAsButton',
  dataElement: 'presetButton-save'
});

// Print button from the Main Menu
const printButton = new instance.UI.Components.PresetButton({
  buttonType: 'printButton',
  dataElement: 'presetButton-print'
});

// Settings button from the Main Menu
const settingsButton = new instance.UI.Components.PresetButton({
  buttonType: 'settingsButton',
  dataElement: 'presetButton-settings'
});

const header = instance.UI.getModularHeader('default-top-header');

// add all the buttons to the header 
header.setItems([...header.getItems(), downloadButton, saveAsButton, printButton, settingsButton]);

Preset buttons are a new feature in the Modular UI that allow you to easily add buttons to the UI without having to create custom buttons. They are a great way to add buttons to the UI that already have an icon the correct onClick methods.

You can even add other prebuilt items like the Page Controls to the header in the same way.

const pageControls = new instance.UI.Components.PageControls();

// This can now be added to a modular header
const header = instance.UI.getModularHeader('default-top-header')
header.setItems([...header.getItems(), pageControls]);

You can also find some examples that show how to set up a UI config in the UI Import and Export guide .

Trial setup questions? Ask experts on Discord
Need other help? Contact Support
Pricing or product questions? Contact Sales