Using Page References to Open Console Workspace Tabs and Subtabs

You can navigate to different page types, including a URL addressable custom component. To make a custom component URL addressable using LWC, use the lightning__UrlAddressable target. To make an Aura component URL addressable, implement the lightning:isUrlAddressable interface on your custom component.

Use Page References in LWC

You can use a page reference to open different page types in a tab or subtab. This example opens a subtab using openTab() to display the view page on a specified PersonAccount record.

1import { LightningElement, wire } from 'lwc';
2import { EnclosingTabId, openSubtab } from 'lightning/platformWorkspaceApi';
3
4export default class MyComponent extends LightningElement {
5   @wire(EnclosingTabId) enclosingTabId;
6   
7   openAnotherSubTab() {
8     if (!this.enclosingTabId) {
9        return;
10     }
11     openSubtab(this.enclosingTabId, {
12         pageReference: {
13            type: 'standard__objectPage',
14            attributes: {
15                recordId: '001xx000003DGg0AAG',
16                objectApiName: 'PersonAccount',
17                actionName: 'view'
18            }
19         }
20      });
21   }
22}

Navigate to a URL Addressable Component in LWC

Making a component URL addressable provides the following benefits for console apps:

  • Future-proofs your apps from changes in URL formats.
  • Generates a user-friendly URL for your tabs.
  • Opens an Aura component as a subtab, even if called from a utility, a hover, or another page.
  • Allows a mechanism to conditionally open a given component more than once or redirect to an already open workspace or subtab using the uid parameter.

    Other uses for the uid parameter that are not explicitly outlined in this document are not supported.

    Warning

For example, you have a URL addressable myComponent component, and a workspaceOpenTab component that navigates to the addressable component.

To make myComponent available for navigation, set the <isExposed> tag to true in the myComponent.js-meta.xml configuration file. The <apiVersion> tag has no impact on the lightning__UrlAddressable target and can be set to an earlier version.

1<!-- myComponent.js-meta.xml -->
2<?xml version="1.0" encoding="UTF-8"?>
3<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
4    <apiVersion>61.0</apiVersion>
5    <isExposed>true</isExposed>
6    <targets>
7        <target>lightning__UrlAddressable</target>
8    </targets>
9</LightningComponentBundle>

myComponent displays the URL and page reference information that the workspaceOpenTab component passes in.

1<!-- myComponent.html -->
2<template>
3  <div class="slds-var-m-around_medium">
4    <p>Component URL: {connectedCallbackUrl}</p>
5    <p>Current page reference:</p>
6    <pre><code>{currentPageRefFormatted}</code></pre>
7  </div>
8</template>

The component's JavaScript uses the CurrentPageReference wire adapter to return page reference information. In this example, the URL returns https://MyDomainName.my.salesforce.com/lightning/cmp/c__myComponent?c__mystate=value&uid=_uniqueId_.

1// myComponent.js
2import { LightningElement, wire } from 'lwc';
3import { CurrentPageReference } from 'lightning/navigation';
4
5export default class MyComponent extends LightningElement {
6  @wire(CurrentPageReference)
7  currentPageRef;
8
9  connectedCallbackUrl;
10
11  connectedCallback() {
12    this.connectedCallbackUrl = window.location.href;
13  }
14
15  get currentPageRefFormatted() {
16    return JSON.stringify(this.currentPageRef, undefined, 2);
17  }
18}

This workspaceOpenTab has a button that opens the URL addressable component in a new workspace tab. Its .js-meta.xml configuration file includes the lightning__AppPage target only. It assumes that you add the workspaceOpenTab component to a Lightning console app.

1<!-- workspaceOpenTab.html -->
2<template>
3  <div class="slds-m-around_medium">
4      <lightning-button label="Open Tab" onclick={handleOpen}>
5      </lightning-button>
6  </div>
7</template>

The component's JavaScript calls the openTab() method from lightning/platformWorkspaceApi. To prevent the app from opening a new tab if the tab with the component is already opened, pass in a uid value to the state object.

1// workspaceOpenTab.js
2import { LightningElement, wire } from 'lwc';
3import { NavigationMixin } from 'lightning/navigation';
4import { IsConsoleNavigation, openTab } from 'lightning/platformWorkspaceApi';
5
6export default class WorkspaceOpenTab extends NavigationMixin(LightningElement) {
7  @wire(IsConsoleNavigation) isConsoleNavigation;
8
9  async handleOpen() {
10    if (!this.isConsoleNavigation) {
11      return;
12    }
13    try {
14      await openTab({
15        pageReference: {
16          type: 'standard__component',
17          attributes: {
18            componentName: 'c__myComponent',
19          },
20          state: {
21            c__stateKey: 'stateValue',
22            uid: "1",
23          },
24        },
25        icon: 'utility:sparkles',
26        label: 'My Component',
27      });
28    } catch (error) {
29      // handle error
30    }
31  }
32}

Use Page References in Aura Components

To create a page reference we can use to open workspace tabs and subtabs, let’s create greetings.cmp, and implement lightning:isUrlAddressable. This component displays “Hello, <name>” where a URL parameter, c__name, provides the name when the component is opened. The component also defines a pageReference that we can use to navigate to it.
1<aura:component implements="lightning:isUrlAddressable">
2    <aura:attribute name="name" type="String" description="The person that will be greeted" />
3    <aura:handler name="init" value="{!this}" action="{!c.init}" />
4    <aura:handler name="change" value="{!v.pageReference}" action="{!c.handlePageChange}" />
5    <h1>Greeting Page</h1>
6    <div>Hello, {!v.name}</div>
7</aura:component>
The JavaScript controller greetingsController.js handles URL parameters in the init method and assigns the name attribute using that URL parameter.
1({
2    init: function(cmp, evt, hlp) {
3        var myPageRef = cmp.get("v.pageReference");
4        var name = myPageRef && myPageRef.state ? myPageRef.state.c__name : "World";
5        cmp.set("v.name", name);
6    },
7    handlePageChange: function(cmp, evt, hlp) {
8        var myPageRef = cmp.get("v.pageReference");
9        var name = myPageRef && myPageRef.state ? myPageRef.state.c__name : "World";
10        cmp.set("v.name", name);
11    }
12})
Now let’s create openGreetings.cmp, which includes an input field to set the c__name URL parameter when we open greetings.cmp.
1<aura:component>
2    <aura:attribute name="pageReference" type="Object"/>
3    <lightning:workspaceAPI aura:id="workspace"/>
4    <lightning:button label="Open Greeting in Subtab" onclick="{!c.openSubtab}"/>
5    <lightning:input label="Name" name="myname"/>
6</aura:component>

The controller openGreetingsController.js uses openSubtab() and sets c__name to the value of the myname input field. You can use the uid parameter to conditionally dedupe tabs and subtabs. Omit the uid to open a new tab or subtab every time.

1({
2    openSubtab: function(component, event, helper) {
3        var workspaceAPI = component.find("workspace");
4        workspaceAPI.getEnclosingTabId().then(function(enclosingTabId) {
5            workspaceAPI.openSubtab({
6                parentTabId: enclosingTabId,
7                pageReference: {
8                    "type": "standard__component",
9                    "attributes": {
10                        "componentName": "c__greetings"
11                    },
12                    "state": {
13                        "uid": "1",
14                        "c__name": component.get("v.myName")
15                    }
16                }
17            }).then(function(subtabId) {
18                console.log("The new subtab ID is:" + subtabId);
19            }).catch(function(error) {
20                console.log("error");
21            });
22        });
23    }
24})

Now that we have everything set up, we can test our components by creating a custom tab in Setup for openGreetings.cmp. Add the custom tab to a console app and open the console app. Select the custom tab from the nav menu to open openGreetings.cmp. Enter a name and click “Open Greeting in Subtab.” greetings.cmp opens as a subtab and displays its greeting with the provided name.