We have a client who loves the Salesforce Console and uses it a lot. Recently he gave us a task where he needed the tab for creating a new record to be closed when the record is created successfully and then to focus the source tab. Let’s see how we made it work...

The Issue

The issue is that “New Record” is a standard Salesforce functionality and there is no option to control what happens on success. The default behavior is to redirect to the newly created record. Here is the documentation for pageReference which is used for navigating to pages in Salesforce.

I was searching the internet for an existing solution, because I thought that triggering an action after a new record is created does not sound too exotic. Surely there is a result for a very similar feature, asked 3 years ago. Unfortunately the described undocumented solution is no longer valid. Actually it is half valid.

I’ve spent some time debugging how the popup for new records issued from another popup works. I found out that they still use navigationLocation: “LOOKUP” but with additions – reference to the navigationLocationId. After testing those additional undocumented properties I’ve realised that they are used only if our “new record” page is in popup, not in tab as it was in my case. So it was not my solution. I’ve spent more time trying to find something undocumented, but it was hopeless. I’ve concluded that I could not perform any action after successful record creation.

The Solution

Since my page was in a workspace tab where I have full control, I came with the idea that I can actually perform any action from an aura component, placed inside the “record view” page.

Each time I visit my target object’s View page, or I’ve been redirected to it after successful record creation, this component is executed. With the help of workspaceAPI I can easily pull information whether the page is in Tab and all details of the tab. So, by placing some conditions while using Tab details, you could determine if there is a need to perform your desired action.

In my particular case I observe for specific tab type and title, and if it matches – the current Tab gets closed.

Focusing the source tab was also challenging. I could not find a suitable way to send information from which tab we start to the new one. Unfortunately tabs do not support custom payloads at all and I didn't want to involve any object record here. I’ve chosen to send this information via global javascript variables. The variable name is based on the new tab Id and its value is the source tab recordId. Our Lightning component needs only to check if the javascript variable exists and has value. By using this value we can iterate over all tabs in the Console and focus the one who has that recordId.

Implementation

Here is what our component markup looks like:

({
 onInit: function (component, event, helper) {
   // get reference to the workspaceAPI
   const workspaceAPI = component.find('workspace');

   if (workspaceAPI) {
     // ensure that we are in Console
     workspaceAPI.isConsoleNavigation().then(isConsole => {
       if (isConsole) {
         // get our enclosing tab
         workspaceAPI.getEnclosingTabId().then(enclosingTabId => {
           // retrieve full tab info
           workspaceAPI.getTabInfo({
               tabId: enclosingTabId
           }).then(tabInfo => {
             // Conditions
             if (tabInfo.customTitle && tabInfo.customTitle === 'Reply Task' && tabInfo.isSubtab) {
               // Actual action implementation

               // create variable name for retrieving info which tab we should be focusing on
               const varName = `__reply_task_return__${tabInfo.tabId}`;

               if (window[varName]) {
                 const returnToId = window[varName];
                 // delete our helper variable as it is not valid anymore
                 delete window[varName];

                 // retrieve all tabs
                 workspaceAPI.getAllTabInfo().then(tabs => {

                   // search for our destination tab
                   let destinationTab = tabs.find(tab => tab.recordId === returnToId);

                   // It is not our destination tab, but let's search in its sub tabs
                   if (!destinationTab) {
                     tabs.forEach(tab => {
                       tab.subtabs.forEach(subTab => {
                         if (returnToId === subTab.recordId) {
                           destinationTab = subTab;
                         }
                       });
                     });
                   }

                   // if we found our destination tab, then focus on it and close the current one
                   if (destinationTab) {
                     workspaceAPI.focusTab({
                       tabId : destinationTab.tabId
                     }).then(() => {
                       workspaceAPI.closeTab({ tabId: enclosingTabId });
                     });
                   }
                 });
               }
             }
           });
         });
       }
     });
   }
 }
});

And that’s pretty much it.

The only thing left to do is to edit your object’s View page (Task View Page in my case) and put our new component somewhere in the page. The component is not visible so it won’t break your design.

By tuning the conditions and changing the action code itself you can achieve basically any action you want.

Happy Coding!