I am having issues getting a component once it has made it into v.body. supposedly, v.body is a Aura.Component[], but when I get one of its elements I cannot make it behave like a component (can't call methods, or do a .get('v.xxx').

Here is one simple example of what I mean

Markup

<lightning:tabset selectedTabId="checkin" aura:id="tabset">
  <lightning:tab aura:id="checkinTab" label="1" id="checkin"> 
    <c:myComp aura:id="myComp1" />
  </lightning:tab>
  <lightning:tab aura:id="inprocessTab label="2" id="inprocess">
    <c:myComp aura:id="myComp2" />
  </lightning:tab>
  <lightning:tab aura:id="closedTab" label="3" id="closed">
    <c:myComp aura:id="myComp3" />
  </lightning:tab>
</lightning:tabset>

MyComp

<aura:component>
    <aura:method name="doSomething" action="{!c.handledoSomething}"/>
</aura:component>

JS Code

//This gives me an error ('.get is not a function');
var myItem = component.find('tabset').get('v.body')[0];
var myLabel = myItem.get('v.label');

//This gives me an error ('.find is not a function');
var myItem = component.find('checkinTab').find('myComp1');

//This doesn't even work (myItem outputs as undefined)
var myItem = component.find('myComp1')
myItem.doSomething();

//This gives me an error ('.doSomething is not a function');
var myItem = component.find('checkinTab').get('v.body')[0];
myItem.doSomething();

How can I either get the system to find a method for a component inside a tabset, or at least allow me to retrieve that component so I can hit the method myself?

  • Have you tried to use find twice? Like parent.find('child_id').find('inner_cmp_id') – Renato Oliveira Aug 17 at 20:18
  • yup, also errors. (Updated) – Sebastian Kessel Aug 17 at 20:19
  • Perhaps this would be helpful for you: salesforce.stackexchange.com/questions/180539/… – Renato Oliveira Aug 17 at 20:52
  • Renato, unfortunately this does not apply to my case. Putting the child component outside of the tabset eliminates the problems (I can find it and also call a method). The problem is inside the tabset (though this does not explain the v.body behavior) – Sebastian Kessel Aug 17 at 20:54
  • @SebastianKessel one thing I had noticed during one of my PoCs that the content within a tab in a tabset does not gets initialized or is made available until the tab itself is clicked. That will mean that only when it has the focus. That is what must be causing your issue. I couldn't find any documentation related on this behavior so assumed that's how it is. – Jayant Das Aug 17 at 20:58
up vote 7 down vote accepted

Two issues going on here:

  • First is described in the tabset documentation:

    This component creates its body during runtime. You won’t be able to reference the component during initialization.

  • The second issue is similar and occurs after init: the components which are contained in non-selected tabs are unavailable. After focusing a tab, its component contents are then available to be "found" in the page.

During init no tab contents will be found by aura:id.

After init the selected tab's components can be found through normal component.find('aura:id') methods.

After selecting a tab, that tab's components can continue to be found by aura:id even after selecting other tabs in the tabset.

In the screenshot below:

  • myComp3's method is available because Tab #3 has been selected and its body rendered.
  • myComp1's method is still available after selecting Tab #3.
  • Tab #2 has not been selected and thus it's component's method is not yet rendered or available to be called and throws an error.

enter image description here

  • Well, not my favorite result (I needed to this on init) but an answer nonetheless. I'll get refactoring! – Sebastian Kessel Aug 17 at 23:28

I have struggled with find logic related to lightning:tabset and have come to the conclusion - rightly or wrongly - that the problem is with the mixing of namespaces - lighting and c in your case - resulting in the framework blocking the access. Might be hard-wired in the framework or the result of LockerService. The behaviour seems to be that you can't "cross" a component that is in a another namespace to reach components even when those are in the same namespace as your code.

I've resorted to registering child objects (c:comp2 below) when they are created in an attribute of the root component (c:comp1 below) so as to be able to access the child objects:

c:comp1
  lightning:tabset
    lightning:tab
      c:comp2

but it is pretty ugly and painful to do so I hope I'm wrong.

  • 1
    Temporarily, I've done the same. I am saving the content of each tab in a variable of type Aura:Component in the parent component. Then I can do a nice "find" and then call my method. Not a permanent solution, but endorses your view. – Sebastian Kessel Aug 17 at 23:10

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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