> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/ui-customization/multi-tab.md).

# Enable and Use Multi-Tab Document Viewing in WebViewer

Discover how to enable multi-tab document viewing using web with ease. Learn how to open multiple documents simultaneously using WebViewer's API and feature toggle. The Apryse Web SDK streamlines secu

## Open Multiple Documents in WebViewer

In WebViewer version 8.3+ you can open multiple tabs in WebViewer. The API, feature toggle, and Events are available in version 8.4+

There are two ways to enable Multi-tab mode. Passing an array of 2 or more documents to the WebViewer constructor in the `initialDoc` property or using the `enableFeatures` API.

### Enabling via Webviewer constructor

When creating a new instance of WebViewer, the `initialDoc` property needs to be set with the list of documents to be opened in the tabs.

To declare extensions for these documents, you must provide an array of extensions to the WebViewer constructor via `extension` property. The array of extensions must be the same length as the array of documents, with the indexes corresponding to the indexes of the documents in `initialDoc`.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  initialDoc: ["pdf_doc.pdf", "doc_doc.docx"],
  extension: ["pdf", "docx"],
  path: '/lib',
}, viewerElement);
```

{% endcode %}
{% endtab %}
{% endtabs %}

If all the documents passed to the constructor are the same type, you can pass in a single string to the extension array.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  initialDoc: ["pdf_doc.pdf", "pdf_doc2.pdf", "pdf_doc3.pdf"],
  extension: ["pdf"],
  path: '/lib',
}, viewerElement);
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Enabling using Webviewer API

To enable/disable Multi-tab mode without the constructor, you can use the WebViewer API with the enableFeatures function. (v8.4+)

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  path: '/lib',
}, viewerElement).then(function(instance) {
  instance.UI.enableFeatures([instance.UI.Feature.MultiTab]);
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

### API

To interact with the API you can wrap your TabManager code around the onTabManagerReadyEvent. (v10.1+) This will ensure that the TabManager has been initialized before any calls are made.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
const { UI, Core } = instance
UI.addEventListener(UI.Events.TAB_MANAGER_READY, async () => {
  await UI.TabManager.addTab('https://pdftron.s3.amazonaws.com/downloads/pl/form1.pdf', { setActive: true });
});
UI.enableFeatures(['MultiTab']);
```

{% endcode %}
{% endtab %}
{% endtabs %}

The multi-tab api is available through the TabManager class. (v8.4+) Using this API you can open new tabs, close tabs, and switch between tabs programmatically. Here are the available methods:

* [addTab()](https://sdk.apryse.com/api/web/UI.TabManager.html#.addTab__anchor)
* [deleteTab()](https://sdk.apryse.com/api/web/UI.TabManager.html#.deleteTab__anchor)
* [getActiveTab()](https://sdk.apryse.com/api/web/UI.TabManager.html#.getActiveTab)
* [getAllTabs()](https://sdk.apryse.com/api/web/UI.TabManager.html#.getAllTabs__anchor)
* [setActiveTab()](https://sdk.apryse.com/api/web/UI.TabManager.html#.setActiveTab__anchor)

The addTab() method takes in a source to load the document from and the load options. See guide for [supported addTab options](https://sdk.apryse.com/api/web/UI.html#.addTabOptions).

When `setActive` is set to true, the tab will be loaded immediately after creation. When `saveCurrentActiveTabState` is set to true (only applicable with setActive=true), the current tab's state will be saved prior to loading the new tab.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
let options = {
  extension: 'pdf',
  filename: 'file1.pdf', // Used as the name of the tab
  setActive: true, // Defaults to true
  saveCurrentActiveTabState: false, // Defaults to true
};
instance.UI.TabManager.addTab("https://demo.apryse.com/file1.pdf", options).then(function(newTabId) {
  console.log(newTabId);
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Events

You can also listen for events when tabs are modified using the UI namespace event listeners. Here are the relevant events:

* [UI.Events.BEFORE\_TAB\_CHANGED](https://sdk.apryse.com/api/web/UI.html#event:beforeTabChanged__anchor)
* [UI.Events.TAB\_DELETED](https://sdk.apryse.com/api/web/UI.html#event:tabDeleted__anchor)
* [UI.Events.TAB\_ADDED](https://sdk.apryse.com/api/web/UI.html#event:tabAdded__anchor)
* [UI.Events.TAB\_MOVED](https://sdk.apryse.com/api/web/UI.html#event:tabMoved__anchor)

Below is some sample usage of the TAB\_ADDED event.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  path: '/lib',
}, viewerElement).then(function(instance) {
  const { UI } = instance;
  const { Events } = UI;
  UI.addEventListener(Events.TAB_ADDED, e => {
    const { detail } = e;
    console.log(detail.src); // Source of the new tab
    console.log(detail.options); // Document load options
  });
});
```

{% endcode %}
{% endtab %}
{% endtabs %}

### IndexedDB

Multi-tab mode will use the browsers built in IndexedDB to save the state of the tabs. If your browser does not support IndexedDB, you will not be able to save the tab state when switching tabs. To disable the usage of IndexedDB you can pass in true to the disableIndexedDB option in the WebViewer constructor:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
WebViewer({
  path: '/lib',
  disableIndexedDB: true, // Defaults to false
}, viewerElement);
```

{% endcode %}
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/ui-customization/multi-tab.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
