[SalesForce] Salesforce Lightning: Dynamically Create Tabset/Tab

I'm currently having an issue when trying to tabset with dynamic tabs. It appears that I need to use "aura:set" to set the label for each tab. When I do that though, I receive the oh so incredibly helpful "An internal server error has occurred Error ID: xxxxxxxxxxxxxxxx.

Exact Error Messages (Scroll right for error codes)

Error : [{"status":"SUCCESS","message":""},{"status":"SUCCESS","message":""},{"status":"ERROR","message":"An internal server error has occurred\nError ID: 2003145941-42295 (-1127739456)"},{"status":"SUCCESS","message":""},{"status":"ERROR","message":"An internal server error has occurred\nError ID: 2003145941-42296 (-1127739456)"},{"status":"SUCCESS","message":""},{"status":"ERROR","message":"An internal server error has occurred\nError ID: 2003145941-42297 (-1127739456)"}]

Here is a quick distillation of what I'm trying to do:

MyComponent.cmp

<aura:component description="TabSetExample">
    <aura:attribute name="horizontalTabs" type="Aura.Component[]" access="private"/>
    <aura:handler name="init" action="{!c.onInit}" value="this"/>
    {!v.horizontalTabs}
</aura:component>

MyComponentController.js

({
    onInit : function(component, event, helper) {
        helper.createTabset(component);
    }
})

MyComponentHelper.js

({
    createTabset: function(component) {
        var newComponents = [];
        newComponents.push(["lightning:tabset", {
            "aura:id" : "tabset",
            "variant" : "default"
        }]);
        newComponents.push(["lightning:tab", {
            "id" : "tab1"
        }]);
        newComponents.push(["aura:set", {
            "attribute": "label",
            "body": "Tab 1"
        }]);
        newComponents.push(["lightning:tab", {
            "id" : "tab2"
        }]);
        newComponents.push(["aura:set", {
            "attribute": "label",
            "body": "Tab 2"
        }]);
        newComponents.push(["lightning:tab", {
            "id" : "tab3"
        }]);
        newComponents.push(["aura:set", {
            "attribute": "label",
            "body": "Tab 3"
        }]);
        $A.createComponents(newComponents,
            function (components, status, errorMessage) {
                if (component.isValid() && status === "SUCCESS") {
                    var tabset = components[0];
                    var tabs = [];
                    for(var i = 1; i < components.length; i++) {
                        if(i % 2 === 0) {
                            components[i-1].set("v.label", components[i]);
                        } else {
                            tabs.push(components[i]);
                        }
                    }
                    tabset.set("v.body", tabs);
                    component.set("v.horizontalTabs", tabset);
                } else {
                    //log error
                }
            }
        );
    }
})

It appears as though the I'm unable to generate an "aura:set" component (is this actually a component?). If I can't generate the "aura:set" dynamically, does anyone know of a way to dynamically set the label of a "lightning:tab"? I've tried a String and an "aura:html" setup as a span, neither works.

Best Answer

You can't initialize an aura:set component. It causes Bad Things to happen. The label attribute is a Component[] value so you need to create an aura:text component and then assign it to the label after component generation.

The code should look something more like this:

({
    createTabset: function(component) {
        var newComponents = [];
        newComponents.push(["lightning:tab", {
            "id" : "tab1",
            "title": "Tab 1"
        }]);
        newComponents.push(["aura:text",{
            "value" : "Tab 1"
        }]);
        newComponents.push(["lightning:tab", {
            "id" : "tab2",
            "title": "Tab 2"
        }]);
        newComponents.push(["aura:text",{
            "value" : "Tab 2"
        }]);
        newComponents.push(["lightning:tab", {
            "id" : "tab3",
            "title": "Tab 3"
        }]);
        newComponents.push(["aura:text",{
            "value" : "Tab 3"
        }]);
        $A.createComponents(newComponents,
            function (components, status, errorMessage) {
                console.log(errorMessage);
                if (component.isValid() && status === "SUCCESS") {
                    var tabs = [];
                    for(var i = 0; i < components.length; i++) {
                        if(i % 2 === 0) {
                            tabs.push(components[i]);
                        } else {
                            components[i-1].set("v.label", components[i]);
                        }
                    }
                    component.set("v.horizontalTabs", tabs);
                } else {

                }
            }
        );
    }
})

It appears you have to set the tab bodies before they'll render, or perhaps I'm missing something else, but at minimum, this no longer errors.