The workspace API allows you to perform console-related tasks that include opening tabs and subtabs and to adding focus to opened tabs and subtabs. To use the API, you need to include the Lightning Component Lightning :workspaceAPI in the component.
The following shows the code snippet on how to use the API:
<aura:component implements="flexipage:availableForAllPageTypes" access="global"> <Lightning :workspaceAPI aura:id="workspace"/> <Lightning :button label="Close Focused Tab" onclick="{!c.closeFocusedTab}"/> </aura:component>
The controller code is as follows:
({
closeFocusedTab : function(component, event, helper) {
var workspaceAPI = component.find("workspace");
workspaceAPI.getFocusedTabInfo().then(function(response) {
var focusedTabId = response.tabId;
workspaceAPI.closeTab({tabId: focusedTabId});
})
.catch(function(error) {
console.log(error);
});
}
})
To demonstrate how to leverage the workspace API, let's create a demo component that opens contacts linked to the account, which are currently viewed as the tabs and cases as subtabs.
Again, the demo component is a simple Utility Bar component and listens for the Account view and uses a record change event to find the recordId. We implement two buttons: one to open tabs and another to open subtabs. The following screenshot shows the component screen:
The component markup code is shown as follows (note the snippets highlighted in bold, which are used to observe the handler and the API markup):
<aura:component implements="force:hasRecordId,flexipage:availableForAllPageTypes" controller="AccountController">
<aura:handler name="change" value="{!v.recordId}" action="{!c.onRecordIdChange}"/>
<aura:attribute name="currentFocusedTabId" type="String" />
<Lightning :workspaceAPI aura:id="workspace"/>
<div class="slds-m-around_medium">
<Lightning :button label="Open Contacts As Tabs" onclick="{! c.openContacts }" />
</div>
<div class="slds-m-around_medium">
<Lightning :button label="Open Cases As SubTabs" onclick="{! c.openCases }" />
</div>
</aura:component>
The controller code is as follows (notice that we use the ES6 arrow functions and promises extensively):
({
onRecordIdChange : function(component, event, helper) {
var newRecordId = component.get("v.recordId");
console.log(newRecordId);
//Get the Focused TabId
var workspaceAPI = component.find("workspace");
workspaceAPI.getFocusedTabInfo().then(function(response) {
var focusedTabId = response.tabId;
component.set("v.currentFocusedTabId",focusedTabId);
})
},
openContacts : function(component, event, helper) {
helper.getAccountPromise(component, event).then(
// resolve handler
$A.getCallback((result) => {
var accountObj = JSON.parse(result);
var workspaceAPI = component.find("workspace");
var promiseArray = [];
accountObj.Contacts.records.forEach((element) => {
var workSpaceAPIPromise = workspaceAPI.openTab({
recordId: element.Id,
focus: true
});
promiseArray.push(workSpaceAPIPromise);
});
promiseArray.all(promiseArray);//open all the Windows using Promise.all
}),
// reject handler
$A.getCallback((error) => {
console.log("Promise was rejected: ", error);
})
)
},
openCases : function(component, event, helper) {
helper.getAccountPromise(component, event).then(
// resolve handler
$A.getCallback((result) => {
var accountObj = JSON.parse(result);
var workspaceAPI = component.find("workspace");
var promiseArray = [];
accountObj.Cases.records.forEach((element) => {
var workSpaceAPIPromise = workspaceAPI.openSubtab({
parentTabId: component.get("v.currentFocusedTabId"),
recordId: element.Id,
focus: true
});
promiseArray.push(workSpaceAPIPromise);
});
promiseArray.all(promiseArray);//open all the Windows using Promise.all
}),
// reject handler
$A.getCallback((error) => {
console.log("Promise was rejected: ", error);
})
)
},
})
The helper function holds the promise to make Apex calls to find the cases and contacts:
({
getAccountPromise : function(component, event) {
return new Promise($A.getCallback( (resolve, reject) => {
var action = component.get("c.getAccountInfo");
action.setParams({ recordId : component.get("v.recordId") });
action.setCallback(this, (response) => {
var state = response.getState();
if (state === "SUCCESS") {
resolve(response.getReturnValue());
}
else {
reject(response.getError());
}
});
$A.enqueueAction(action);
}));
},
})
The Apex controller code is as follows:
public with sharing class AccountController {
@AuraEnabled
public Static String getAccountInfo(String recordId){
String response = '{}';
list<Account> lstaccounts = [Select Id,
Name ,
(Select Id FROM Contacts),
(Select Id from Cases)
FROM Account
WHERE ID =:recordId];
if(lstaccounts.size() >0 ){
response = JSON.serialize(lstaccounts[0]) ;
}
return response;
}
}
The following screenshot shows how the user interface opens tabs and subtabs upon clicking the relevant buttons: