Before I start, I'm not referring to <aura:template />
for bootstrapping the Aura framework. That's something different. What I mean is I would like to create a "template" to use for generating components at runtime. The ComponentDefRef
type seems to be the way to do this, but there isn't much in the way of documentation.
Take a look at <aura:if />
. It has two attributes, body and else, of type ComponentDefRef[]
. Internally, it takes these attribute values and generates components from them and inserts the components into the app. You can look at the source here. <aura:iteration />
works in a similar way. Its body is of type ComponentDefRef[]
and is used to generate a list of components.
I would like to create a Lightning component which does something similar. I would like to take a ComponentDefRef[]
, turn it into a Component[]
, and insert it into the component hierarchy for rendering. I've struggled with this for a few days with no luck.
As an example, take the app and component below. When I try to run it, Salesforce returns an error:
An internal server error has occurred Error ID: 1176784454-8959 (-227057212)
Keep in mind this is a contrived example to illustrate what I want to do. What I'm trying to build is a grid control.
testTemplate.cmp
<aura:component>
<aura:attribute name="var" type="String" />
<aura:attribute name="indexVar" type="String" />
<aura:attribute name="items" type="Object[]" />
<aura:attribute name="template" type="Aura.ComponentDefRef[]" />
<aura:iteration items="{!v.items}" var="{!v.var}" indexVar="{!v.indexVar}" template="{!v.template}" />
</aura:component>
tester.app
<aura:application extends="force:slds">
<aura:attribute name="countries" type="Object[]" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<div class="slds">
<div class="slds-grid">
<div class="slds-col slds-p-around--small">
<c:testTemplate items="{!v.countries}" var="country" indexVar="i">
<aura:set attribute="template">
<div>{!i}. The capital of {!country.name} is {!country.capital}.</div>
</aura:set>
</c:testTemplate>
</div>
</div>
</div>
</aura:application>
testerController.js
({
doInit: function(component, event, helper) {
var countries = [{
name: 'France',
capital: 'Paris'
}, {
name: 'Britian',
capital: 'London'
}, {
name: 'Spain',
capital: 'Madrid'
}];
component.set('v.countries', countries);
}
})