1

I have a lightning:tabset with one tab containing a list of records. When user clicks on a button next to a record I want to display a second tab with the record detail.

My component looks like this:

<aura:component>
    <lightning:tabset aura:id="tabset">
        <lightning:tab label="Record List" aura:id="tab1">
            <!-- list of records -->
        </lightning:tab>
    </lightning:tabset>
</aura:component>

The handler for the click event looks like this:

showRecordDetailTab: function(component, event, helper) {
    $A.createComponent(
        'lightning:tab',
        {
            'aura:id': 'accountViewTab',
            'label': 'Account Detail'
        },
        function(newTab, status, errorMessage) {
            if (status === 'SUCCESS')
            {
                var tabset = component.find('tabset');
                var tabsetBody = tabset.get('v.body');
                tabsetBody.push(newTab);
                tabset.set('v.body', tabsetBody);
            }
            else if (status === 'ERROR')
            {
                console.log('Error: ' + errorMessage);
            }
        }
    );
}

I am having 2 issues:

  1. The above code is not working, as in the new tab is not being created on the DOM
  2. I am not sure how to define the body of the tab. To display a standard record layout do I use a nested createComponent action that creates force:recordView? Or do I add a property for v.body to my new tab containing force:recordView?
6

I think the key thing is that you need to set the tab body on component creation.

Here's an example (minus error handling) that sets the tab body to a ui:outputText

Notice that the components are created as an array.

$A.createComponents([
    ['lightning:tab', {
            'aura:id': 'accountViewTab',
            'label': 'Account Detail'
    }],
    ["ui:outputText",{
        "value" : "test"
    }]
    ],
    function(components, status, errorMessage){
        if (status === "SUCCESS") {
            var tab = components[0];
            var outputText = components[1];
            // set the body of the lightning:tab to be the ui:outputText
            tab.set("v.body", outputText);

            //now do as you were doing before
            var tabset = component.find('tabset');
            var tabsetBody = tabset.get('v.body');
            tabsetBody.push(newTab);
            tabset.set('v.body', tabsetBody);
        }
    }
);

EDIT

While this often works, it appears that the use of a ComponentDefRef[] as the body of the tabset, rather than a standard Component[], means that you pretty much can't set the body of a tabset dynamically.

The only way I could get it to work was to use an aura:if and turn it on and off dynamically. I was able to get it to focus nicely, using the valueRender event.

Try this (and apologies that the first technique didn't work):

<aura:attribute name="showDetail" type="Boolean" default="false" />
<aura:handler name="render" value="{!this}" action="{!c.onRender}"/>

<lightning:tabset aura:id="tabset">
  <lightning:tab label="Record List" aura:id="tab1" id="tab1">
    <label>test</label>
  </lightning:tab>
  <aura:if isTrue="{!v.showDetail}">
    <lightning:tab label="Account Detail" aura:id="tab2" id="tab2">
      <label>detail</label>
    </lightning:tab>
  </aura:if>
</lightning:tabset>

<div onclick="{!c.handleClick}">click me</div>

Controller:

handleClick: function(component, event, helper) {
  component.set("v.showDetail",true);
},
onRender : function(component, event, helper) {
  var tab2 = component.find("tab2");
  var tabset = component.find("tabset");
  if (!tab2){
    return;
  }
  tabset.set("v.selectedTabId","tab2");
},
  • When I do console.dir(components) I can see both components being created (and isValid() is true for both), but this error is what I get: Uncaught Action failed: lightning:tab$controller$handleBodyChange [Cannot read property 'dispatchEvent' of null]. Does this mean that the newly created tab is null? Btw as mentioned earlier, with my original script the tab wasn't getting added to the DOM at all. – Mossi2 Jul 24 '17 at 18:31
  • I think you might want to call component creation from the renderer - or hook into the valueRender function. It's likely that the dom is not ready by the time you are attempting to add to the tab. I'd go with the valueRender. Look here: developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – Caspar Harmer Jul 24 '17 at 19:04
  • In my original script I was adding a tab to an already-rendered tabset but the tab wasn't showing up. Just so that I am clear are you saying the tabset might be rerendered before its body is set? – Mossi2 Jul 24 '17 at 20:05
  • No, in that case, if the tabset is already rendered, the valueRender event won't help you. Try a timeout function with a small delay, try debugging using the developer console and put a breakpoint inside the component creation callback – Caspar Harmer Jul 24 '17 at 20:14
  • The new idea works for me! – Mossi2 Jul 24 '17 at 22:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.