0

When I try to take the elements from inside the v.body attribute of my Lightning Component and put them into another structure (e.g. a 2D array, or an Object), they seem to get mangled to the wrong type and don't display correctly. Is there some way around this?

Here's an example app I built to test the behaviour:

TestContainer.cmp

<aura:component description="TestContainer">
    <aura:attribute name="body2D" type="Object[]" access="private" />

    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <lightning:card title="From v.body">
        <aura:iteration var="thisBodyItem" items="{!v.body}">
            {!thisBodyItem}
        </aura:iteration>
    </lightning:card>

    <lightning:card title="From 2D array, v.body2D">
        <aura:iteration var="bodyRow" items="{!v.body2D}">
            <aura:iteration var="thisBodyItem" items="{!bodyRow}">
                {!thisBodyItem}
            </aura:iteration>
        </aura:iteration>
    </lightning:card>

    <lightning:card title="From 2D array, via TestContainerRow">
        <aura:iteration var="bodyRow" items="{!v.body2D}">
           <c:TestContainerRow bodyRow="{!bodyRow}" />
        </aura:iteration>
    </lightning:card>

</aura:component>

TestContainerController.js:

({
    doInit : function(component, event, helper) {
        var body = component.get('v.body');
        var body2D = [[]];
        body.forEach(function (thisBodyItem) {
            body2D[0].push(thisBodyItem);
        })
        component.set('v.body2D', body2D);
    }
})

TestContainerRow.cmp:

<aura:component description="TestContainerRow">
    <aura:attribute name="bodyRow" type="Object[]" access="public" />

    <aura:iteration var="thisBodyItem" items="{!v.bodyRow}">
        {!thisBodyItem}
    </aura:iteration>
</aura:component>

And finally, the app, TestContainerApp.app:

<aura:application description="TestContainerApp">

    <c:TestContainer>
        <ui:message title="foo" severity="info"/>
    </c:TestContainer>

</aura:application>

What we're doing is passing a <ui:message> in as the single item in the body array for the <c:TestContainer>. Then displaying it in various ways:

  • First by a normal <aura:iteration> which works as expected
  • Second by stuffing the body into a 2D array and 2 levels of <aura:iteration> which prints SecureComponentRef: markup://ui:message {4:0}{ key: {"namespace":"c"} } instead of the actual <ui:message>
  • Third, I tried going via the <c:TestContainerRow> which encapsulates a row

Some things along the way:

  • I was not able to declare the body2D attribute as Aura.Component[][] which is what it should be. This gives a save-error, so it had to be Object[]
  • I was not able to declare bodyRow in <c:TestContainerRow> as Aura.Component[], this gives a runtime error:

Component.createComponentStack: invalid config. Expected component definition, found 'SecureComponentRef: markup://ui:message {4:0}{ key: {"namespace":"c"} }'. Failing descriptor: {aura:iteration}

There are numerous applications where this would be useful e.g. displaying a list of components with some extra metadata associated with them, it would be nice to have the JS controller make a list of objects which contain the component and the metadata together. Or, in my case, displaying the list of components in a table where I cannot use a flexbox-based solution like <lightning:layout>

  • FWIW, I added this idea to suggest that Salesforce give us an attribute called "data" that we can use to attach custom data to system components, which it seems would solve at least one of your use cases. – sfdcfox Mar 28 '18 at 14:19
  • Thanks - I saw that idea via twitter. I think the argument against it on performance reasons is pretty strong, though. Lightning is slow enough already! – Aidan Mar 29 '18 at 12:37
  • I'm pretty sure the performance isn't nearly as bad as they think it'll be. I'm setting up a copy of aura to test it out, but I have to do this in a VM, since Aura doesn't support Windows... – sfdcfox Mar 29 '18 at 13:51

Your Answer

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

Browse other questions tagged or ask your own question.