Containers

Overview

Containers are the top-level components that hold all the other components. They are responsible for the layout of the UI and can be nested to create complex layouts.

Some commonly used containers include Modular Headers, Grouped Items, and Ribbon Groups.

Apryse Docs Image

Modular headers are the highest level of containers and can contain other containers and items. Grouped items are containers that can hold any kind of item, including other grouped items. Ribbon groups are containers that can only hold ribbon items.

Modular Header

Modular headers are the containers at the highest level. These are the containers that many other components will be placed in. The default UI only has top-aligned headers, but they are able to be placed on the top, left, right, and bottom.

Apryse Docs Image

This means that by switching a property on the header, you can quickly move its position. In the example below, the tools header is set to be on the left.

Apryse Docs Image

There are some restrictions on modular headers, mainly:

  • Top headers allow up to two headers stacked on each other
  • The remaining positions only allow one header

DataElements are unique keys

In these guides you will see the usage of dataElements; these should be thought of as unique identifiers for each visual component. If the UI detects duplicate dataElements, it will throw a console warning and add a unique identifier. These dataElements can be used to enable or disable elements, as well as toggle their visibility. For more information on these APIs, please refer to the documentation .

The example below shows how to create a top header similar to the one used in the default UI. It also shows some of the options it accepts, such as grow and style. For more details on these options please refer to the API documentation for ModularHeader

JavaScript

1Webviewer.WebComponent({
2 path: '/lib',
3 ui: 'beta',
4}, viewerElement).then((instance) => {
5 const { UI, Core } = instance;
6 const { Tools } = Core;
7
8 // First we define four items that will be placed in the header.
9 // Please refer to the Items page for more info on the
10 // items that can live inside headers.
11
12 // Menu Flyout Button
13 const mainMenu = new UI.Components.MainMenu();
14 // View Controls
15 const viewControlsToggle = new UI.Components.ViewControls();
16 // Zoom Controls
17 const zoomControls = new UI.Components.Zoom();
18 // Pan Tool Button
19 const panToolButton = new UI.Components.ToolButton({
20 dataElement: 'panToolButton',
21 toolName: Tools.ToolNames.PAN,
22 });
23
24
25 // Creater a top header where we will add the above items
26 const topHeader = new instance.UI.Components.ModularHeader({
27 dataElement: 'default-top-header',
28 placement: 'top',
29 grow: 0,
30 gap: 12,
31 position: 'start',
32 stroke: true,
33 dimension: {
34 paddingTop: 8,
35 paddingBottom: 8,
36 borderWidth: 1
37 },
38 style: {},
39 items: [
40 mainMenu,
41 viewControlsToggle,
42 zoomControls,
43 panToolButton,
44 ]
45 });
46
47 // Set the modular header in the UI
48 instance.UI.setModularHeaders([topHeader]);
49});

addModularHeaders

This API allows you to add headers to the existing UI; it is an additive operation. This means that if you call this API multiple times, it will add the headers to the UI, not replace them. In the example above, if we used this API instead of setModularHeaders, the top header would have been added to the existing UI. This API is useful when you want to add a header to the default UI.

Example usage:

JavaScript

1const { Tools } = instance.Core;
2// Pan Tool Button
3const panToolButton = new instance.UI.Components.ToolButton({
4 dataElement: 'panToolButton',
5 toolName: Tools.ToolNames.PAN,
6});
7
8const topHeader = new instance.UI.Components.ModularHeader({
9 dataElement: 'default-top-header',
10 placement: 'top',
11 grow: 0,
12 gap: 12,
13 position: 'start',
14 stroke: true,
15 dimension: {
16 paddingTop: 8,
17 paddingBottom: 8,
18 borderWidth: 1
19 },
20 style: {},
21 // As an example we add the pan tool button to the top header
22 items: [panToolButton]
23});
24
25instance.UI.addModularHeaders([topHeader]);

setModularHeaders

This API sets the headers for the UI, replacing any existing headers. This is useful when you want to replace the default headers with your own.

Example usage:

JavaScript

1const { Tools } = instance.Core;
2// Pan Tool Button
3const panToolButton = new instance.UI.Components.ToolButton({
4 dataElement: 'panToolButton',
5 toolName: Tools.ToolNames.PAN,
6});
7
8const topHeader = new instance.UI.Components.ModularHeader({
9 dataElement: 'default-top-header',
10 placement: 'top',
11 grow: 0,
12 gap: 12,
13 position: 'start',
14 stroke: true,
15 dimension: {
16 paddingTop: 8,
17 paddingBottom: 8,
18 borderWidth: 1
19 },
20 style: {},
21 // As an example we add the pan tool button to the top header
22 items: [panToolButton]
23});
24
25instance.UI.setModularHeaders([topHeader]);

getModularHeaderList

This API will return a list of all the modular headers in the current UI. The modular headers are encapsulated in class instances that have handy methods that give you the capability to dynamically update headers. For the methods available for each class please refer to the documentation of each class.

Example usage:

JavaScript

1const modularHeaders = instance.UI.getModularHeaderList();

getModularHeader

If you already know the dataElement of the header you wish to manipulate you can use this API. You can find the dataElements by inspecting the UI using your browser’s dev tools.

Example usage:

JavaScript

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

getGroupedItems

Returns the grouped items contained in the header. Note that it will only return the grouped items contained at the top level - it will not recursively find all grouped items contained within this header.

Example usage:

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const topHeaderGroupedItems = topHeader.getGroupedItems()

getItems

This method will return all the items contained in the header. It takes an optional parameter of itemType; if passed it will return the items contained in the header that match this type.

Example usage:

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2// Returns all items contained in the header
3const topHeaderItems = topHeader.getItems()
4// Returns all items of type toggleButton
5const topHeaderToggleButtons = topHeader.getItems('toggleButton')

setGap

This method allows you to set the gap between header items. It takes an integer value in pixels.

Example usage:

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2topHeader.setGap(50)

setItems

Sets the child items of the modular header. This method will remove any invalid items.

Example usage:

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const stylePanelToggle = new instance.UI.Components.ToggleElementButton({
3 dataElement: 'stylePanelToggle',
4 toggleElement: instance.UI.Panels.STYLE,
5 img: 'icon-style-panel-toggle',
6 title: 'Style Panel',
7 });
8
9// This replaces all items in the header
10topHeader.setItems([stylePanelToggle])

setJustifyContent

Sets the content justification within a header. The header can be thought of as a flex container and this is the property to set the justification of the flex items. The value can be one of start, end, flex-start, flex-end, center, space-between, space-around, or space-evenly.

Example usage:

JavaScript

1const toolsHeader = instance.UI.getModularHeader('tools-header')
2toolsHeader.setJustifyContent('start')

setStyle

This method allows you to pass your own style object, overriding the default styles.

Example usage:

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2topHeader.setStyle({
3 background: 'aliceblue',
4 border: '8px dashed',
5 padding: '8px 12px'
6});

Grouped Items

Grouped items are light-weight containers that are placed in other containers and can house any kind of item. In the WebViewer default modular UI, grouped items are used mainly for holding tool buttons and action buttons that interact with the document. They can also house other grouped items. They work similarly to flex-box containers and can be styled like them.

Apryse Docs Image

If there is not enough space for all grouped items to be displayed in their container, there will be a more button (...) that will show in the container which will allow the user to see the rest of the items.

Apryse Docs Image

In the default UI, grouped items are used to hold the buttons in the top header. The example below shows how to create a grouped item similar to one the default UI.

JavaScript

1const { Tools } = instance.Core;
2
3// Create some components that can go into a grouped items container
4// Menu Flyout Button
5const mainMenu = new instance.UI.Components.MainMenu();
6// View Controls
7const viewControlsToggle = new instance.UI.Components.ViewControls();
8// Zoom Controls
9const zoomControls = new instance.UI.Components.Zoom();
10// Pan Tool Button
11const panToolButton = new instance.UI.Components.ToolButton({
12 dataElement: 'panToolButton',
13 toolName: Tools.ToolNames.PAN,
14});
15// create the grouped items container
16const groupedLeftHeaderButtons = new instance.UI.Components.GroupedItems({
17 dataElement: 'groupedLeftHeaderButtons',
18 grow: 0,
19 gap: 12,
20 position: 'start',
21 style: {},
22 items: [
23 mainMenu,
24 viewControlsToggle,
25 zoomControls,
26 ],
27 // either make this visible all the time or only when active
28 alwaysVisible: true,
29});
30
31// now we can add this grouped items container to a modular header
32const defaultTopHeader = new instance.UI.Components.ModularHeader({
33 dataElement: 'default-top-header',
34 placement: 'top',
35 grow: 0,
36 gap: 12,
37 position: 'start',
38 stroke: true,
39 dimension: {
40 paddingTop: 8,
41 paddingBottom: 8,
42 borderWidth: 1
43 },
44 style: {},
45 items: [
46 groupedLeftHeaderButtons,
47 ]
48});
49
50instance.UI.setModularHeaders([defaultTopHeader]);

If a grouped items container is set to 'alwaysVisible: true', it will always be visible, even if it is not active. If it is set to 'alwaysVisible: false', it will only be visible when it is active (i.e. set by a Ribbon Item). The default value is false.

You can also add a grouped items container to a modular header after it has been created. Let's reuse our example from above and add the grouped items container to the top header.

JavaScript

1const { Tools } = instance.Core;
2
3// Create some components that can go into a grouped items container
4// Menu Flyout Button
5const mainMenu = new instance.UI.Components.MainMenu();
6// View Controls
7const viewControlsToggle = new instance.UI.Components.ViewControls();
8// Zoom Controls
9const zoomControls = new instance.UI.Components.Zoom();
10// Pan Tool Button
11const panToolButton = new instance.UI.Components.ToolButton({
12 dataElement: 'panToolButton',
13 toolName: Tools.ToolNames.PAN,
14});
15// create the grouped items container
16const groupedLeftHeaderButtons = new instance.UI.Components.GroupedItems({
17 dataElement: 'groupedLeftHeaderButtons',
18 grow: 0,
19 gap: 12,
20 position: 'start',
21 style: {},
22 items: [
23 mainMenu,
24 viewControlsToggle,
25 zoomControls,
26 ],
27 // either make this visible all the time or only when active
28 alwaysVisible: true,
29});
30
31const topHeader = instance.UI.getModularHeader('default-top-header')
32
33// or you can add the grouped items to the header after it has been created
34topHeader.setItems([groupedLeftHeaderButtons])

Grouped items can be modified in two ways: by calling methods directly on the class instances, or by calling several generic APIs. The generic APIs can modify properties of specific grouped items, or all grouped items, depending on the options passed.

The following APIs have a requirement that the grouped items are already part of the UI - if they have not been added with as part of a header 'addModularHeaders' or 'setModularHeaders' the APIs will have no effect

setGroupedItemsGap

Used to set the gap in pixels for items inside grouped items containers. This can set the property on all grouped items if the second parameter is not provided, or can set it on a specific container if the second parameter is provided with the dataElement of the container being updated.

JavaScript

1// Setting the gap of all Grouped Items
2instance.UI.setGroupedItemsGap(20);
3
4// Setting the gap on Grouped Items with a specific data element
5instance.UI.setGroupedItemsGap(30, {
6 groupedItemsDataElement: 'annotateGroupedItems'
7});

setGroupedItemsGrow

Used to set the grow property of a grouped items container. The grow property is a number specifying how much the item wil grow relative to the rest of the items; it is equivalent to the grow property for flex boxes. This API can set the property on all grouped items if the second parameter is not provided, or can set it on a specific container if the second parameter is provided with the dataElement of the container being updated.

JavaScript

1// Setting the grow property of all Grouped Items
2instance.UI.setGroupedItemsGrow(1);
3
4// Setting the grow property of all Grouped Items with a specific data element
5instance.UI.setGroupedItemsGrow(1, {
6 groupedItemsDataElement: 'group-1'
7});

setGroupedItemsJustifyContent

Used to set the justifyContent property of a grouped items container. This can set the property on all grouped items if the second parameter is not provided, or can set it on a specific container if the second parameter is provided with the dataElement of the container being updated.

JavaScript

1// Setting the justifyContent property of all Grouped Items
2instance.UI.setGroupedItemsJustifyContent('start');
3
4// Setting the justifyContent property of all Grouped Items with a specific data element
5instance.UI.setGroupedItemsJustifyContent('space-between', {
6 groupedItemsDataElement: 'group-1'
7});

Grouped Items Class Methods

These APIs apply to all objects of the Grouped Items class (including Ribbon Group):

setGap(int): Sets the gap between items. Takes a value in pixels.

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const groupedLeftItems = topHeader.getGroupedItems()[0]
3groupedLeftItems.setGap(20)

setGrow(number): Sets the flex-grow property of the items container. The grow property is a number specifying how much the item wil grow relative to the rest of the items; it is equivalent to the grow property for flex boxes.

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const groupedLeftItems = topHeader.getGroupedItems()[0]
3groupedLeftItems.setGrow(1)

setItems(Array): Sets the items in the group, replacing the existing items.

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const groupedLeftItems = topHeader.getGroupedItems()[0];
3const stylePanelToggle = new instance.UI.Components.ToggleElementButton({
4 dataElement: 'stylePanelToggle',
5 toggleElement: instance.UI.Panels.STYLE,
6 img: 'icon-style-panel-toggle',
7 title: 'component.notesPanel',
8 });
9const notesPanelToggle = new instance.UI.Components.ToggleElementButton({
10 dataElement: 'notesPanelToggle',
11 toggleElement: 'notesPanel',
12 img: 'icon-header-chat-line',
13 title: 'component.notesPanel',
14 });
15
16// Replace all items with these two toggle buttons
17groupedLeftItems.setItems([notesPanelToggle, stylePanelToggle])

setJustifyContent(string): Sets the content of the grouped items container. You can think of the container as a flex container, and this is the property to set the justification of the flex items.

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const groupedLeftItems = topHeader.getGroupedItems()[0]
3groupedLeftItems.setJustifyContent('end')

setStyle(Object): Sets the CSS style of the grouped items. This method allows you to pass your own style object, overriding the default styles.

JavaScript

1const topHeader = instance.UI.getModularHeader('default-top-header')
2const groupedLeftItems = topHeader.getGroupedItems()[0]
3groupedLeftItems.setStyle({
4 background: 'aliceblue',
5 border: '8px dashed',
6 padding: '8px 12px'
7});

Ribbon Group

Ribbon Groups are just like grouped items with one exception: they can only house Ribbon Items. This is to ensure consistent styling throughout the UI for things such as the currently active ribbon.

If a non-ribbon item is included in the set of items for a ribbon group, it will be ignored.

Apryse Docs Image

If there is not enough space for all ribbon items to be displayed in their container, there will be a more button (...) that will show in the container which will allow the user to see the rest of the items.

Apryse Docs Image

If there is only enough space for one ribbon item, the ribbon group turns into a dropdown to take up less space.

Apryse Docs Image

The following code sample shows how to create a ribbon group with two ribbon items, each mapping to different grouped items container with certain tools.

JavaScript

1const { Tools } = instance.Core;
2// First let's define some tools that we can place in the grouped items containers
3const highlightToolButton = new instance.UI.Components.ToolButton({
4 dataElement: 'my-highlightToolButton-',
5 toolName: Tools.ToolNames.HIGHLIGHT,
6});
7
8const freeTextToolButton = new instance.UI.Components.ToolButton({
9 dataElement: 'my-freeTextToolButto',
10 toolName: Tools.ToolNames.FREETEXT,
11});
12
13const rectangleToolButton = new instance.UI.Components.ToolButton({
14 dataElement: 'my-rectangleToolButton',
15 toolName: Tools.ToolNames.RECTANGLE,
16});
17
18const polylineToolButton = new instance.UI.Components.ToolButton({
19 dataElement: 'my-polylineToolButton',
20 toolName: Tools.ToolNames.POLYLINE,
21});
22
23// Now we can create two grouped items containers to hold the tools
24const textToolsGroupedItems = new instance.UI.Components.GroupedItems({
25 dataElement: 'textToolsGroupedItems',
26 items: [
27 freeTextToolButton,
28 highlightToolButton,
29 ],
30});
31
32const shapeToolsGroupedItems = new instance.UI.Components.GroupedItems({
33 dataElement: 'shapeToolsGroupedItems',
34 style: {},
35 items: [
36 rectangleToolButton,
37 polylineToolButton,
38 ],
39});
40
41// Now we can create the ribbon items that will map to the grouped items containers
42const textRibbonItem = new instance.UI.Components.RibbonItem({
43 dataElement: 'textRibbonItem',
44 label: 'Text Tools',
45 // Ribbon items can support Icons
46 img: 'icon-tool-text-free-text',
47 groupedItems: ['textToolsGroupedItems'],
48});
49
50const shapeRibbonItem = new instance.UI.Components.RibbonItem({
51 dataElement: 'shapeRibbonItem',
52 label: 'Shape Tools',
53 img: 'icon-tool-shape-rectangle',
54 // This maps to the grouped items container - a ribbon item can map to one or more grouped items containers
55 groupedItems: ['shapeToolsGroupedItems'],
56});
57
58// Now we can create the ribbon group that will hold the ribbon items
59const ribbonGroup = new instance.UI.Components.RibbonGroup({
60 dataElement: 'my-ribbon-group',
61 items: [
62 textRibbonItem,
63 shapeRibbonItem,
64 ],
65});
66
67// Now let's bring it home by adding the ribbon group to the UI
68const topHeader = instance.UI.getModularHeader('default-top-header')
69topHeader.setItems([ribbonGroup])
70// We can also modify the justification in the header so it's centered
71topHeader.setJustifyContent('center')
72
73// And let's also add the tools grouped items to the tools header
74const toolsHeader = instance.UI.getModularHeader('tools-header')
75toolsHeader.setItems([textToolsGroupedItems, shapeToolsGroupedItems])

Running the above code will create the following UI:

Apryse Docs Image

Alternatively, you can create a new header and add your ribbon.

JavaScript

1// create the modular header with the ribbon group set in items
2const defaultTopHeader = new instance.UI.Components.ModularHeader({
3 ...
4 items: [
5 ribbonGroup,
6 ...
7 ]
8});

Ribbon Group Methods

Since Ribbon Groups are a subclass of Grouped Items, they have all the same methods as Grouped Items. See the Grouped Items Class Methods for more information. This means that you can modify the ribbon that is shipped by default using these APIs, instead of creating your own from scratch.

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales