1

Playground link: https://studio.webcomponents.dev/edit/igxyxtS3TKauBJEnQFlV

Error message: Uncaught TypeError: tab.loadContent is not a function

parent.html

<template>
    
    <lightning-tabset>
        <c-child></c-child>
    </lightning-tabset>

</template>

child.html

<template>
    <lightning-tab></lightning-tab>
</template>

For some reason, this doesn't work. It works fine if I have the lightning-tab element at the parent level, but my use case involves setting the label for this element dynamically, which is only possible in a child component.

Is there something simple I'm not seeing here?

4
  • Do you want dynamic label for the lightning-tab?
    – Sneh
    Commented May 28, 2022 at 12:55
  • Yep, based on a child's data.
    – vince
    Commented May 28, 2022 at 13:14
  • 2
    I think this is a X-Y problem. You may want to explain your actual problem a bit better. What do you exactly need? Why won't it work when the tab is in parent?. I think the errors you're getting are expected since lightning-tabset no longer owns lightnint-tab because they're now part of another component & prevent via shadow dom. Commented May 28, 2022 at 13:31
  • 1
    @SachinHooda lightning-tab needs to be part of my child's component, since I need to set the label for the lightning-tab element dynamically. Dynamically means this label is different for each child and there's some logic behind it, i.e. I need to use a getter. I guess it makes sense that lightning-tabset no longer owns lightning-tab. In that case I only see one last resort, which is creating a separate field which is supposed to be the JS getter, having lightning-tab on the parent level and filling in the label there.
    – vince
    Commented May 28, 2022 at 13:46

2 Answers 2

1

All of the elements with nested custom components (e.g. lightning-path, lightning-accordion, lightning-tabset, ...) all suffer from this as a limitation. It happens because the content inside a component is not accessible to components outside of it. A workaround is to notify the parent of the desired label:

<lightning-tabset>
  <lightning-tab>
    <c-my-component ontablabelchange={handleTabLabelChange}>
    </c-my-component>
  </lightning-tab>
</lightning-tabset>

handleTabLabelChange(event) {
  event.target.closest('lightning-tab').label = event.detail.label
}

<template>
  <lightning-button label="Update Label" onclick={handleLabelUpdateButtonClick}>
  </lightning-button>
</template>

  handleLabelUpdateButtonClick() {
    this.dispatchEvent(
      new CustomEvent(
        'tablabelchange',
        { detail: { label: 'Hello World' }}
      )
    )
  }

Demo.

This is only illustrative. You can use renderedCallback(), connectedCallback(), etc to react initially if you want to. You just need to fire off the event when you're ready.

1
  • Thanks for the proposed solution and the clarification about the limitiation :). However, this doesn't work for me as I need the label values when the parent (tabset) component is first inserted. Tab values are, logically speaking, part of the tabset component. In your solution, I end up with a set of empty tabs, up until I click on them, which would, only then, trigger the child's connectedCallback method. I eventually solved it by wiring my data to a function and computing the label value there.
    – vince
    Commented May 29, 2022 at 8:18
0

As @sfdcfox mentioned, all lightning component blocks that require nesting (e.g. lightning-tabset) can't read out a child's content and as such, it's impossible to have lightning-tab as part of the child's component.

I eventually solved it by computing the label's value in my wired function. For example:

    lots;

    @wire(getLots, {caseId: '$recordId'})
    wiredLots({error, data}) {
        if (data) {
            this.lots = data.map((lot) => ({
                ...lot,
                Label : lot.hasOwnProperty('Product__c') ? lot.Product__c : lot.Name
            }));
        }
    }

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .