Using Page References to Open Console Workspace Tabs and Subtabs
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.
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
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>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})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.