How do I use ComponentDefRef to create component "templates" in Salesforce Lightning?

I face similar issues in my current project. I'm trying to create a datatable implementation with columns defined by inner column components in a following matter:

    <c:datatable items="[...]" var="item">

        <c:column>

            <aura:set attribute="header">
                Column Header
            </aura:set>

           Column Body:{!item}
        </c:column>

   </c:datatable>

Now what I've discovered is that you can use Aura.componentdefref[] attribute type to define iteration template and then set this template like any other facet, using attribute:set. Please find an example below:

<aura:component>
    <aura:attribute name="template" type="Aura.componentdefref[]"></aura:attribute>
    <aura:attribute name="var" type="String" ></aura:attribute>
    <aura:attribute name="items" type="Object[]" ></aura:attribute>

    <aura:iteration items="{!v.items}" var="{!v.var}" template="{!v.template}" >
    <!-- Content doesnt matter but it cannot be empty -->
        i 
    </aura:iteration>

</aura:component>

Then you can use component like this:

<c:list var="item" items="[1,2,3,4]">
    <aura:set attribute="template">
        Test template {!item}
    </aura:set>
</c:list>

Output:

Test template 1 Test template 2 Test template 3 Test template 4

There might be way to transform component's body into a template, but I had no luck so far. I hope this information can be of any use to you. It's really hard to find any information on this matter.


To unblock you really quick, Aura.ComponentRefDef is not a thing in lightning.

change

<aura:attribute name="template" type="Aura.ComponentRefDef[]" />

to

<aura:attribute name="template" type="Aura.Component[]" />

in general Internal server error often occure when lightning does not understand the type of the attribute. for example if attribute is of type "String" all good, but if you change it to "text" you will get internal server error. This is a bug, the unrecognized type should not allow you to save the code, but it is what it is.

To analyze your code deeper. if you want to iterate over many element inside your components use {!v.body} facet (this is array of Aura.Component btw) to access original body and then use another facet, for example {!v.modifiedBody} to show the modified bodies. This should work for static html without expressions.

If you will try to pass some expressions in the body - you might run into "value providers" issue. for your example {!country} is not a registered value provider.