9

I am trying to dynamically create a data table with two arrays (SObject array and a String array which has field API name).

The two arrays are Contact[] and String[], where String[] consists of ["Id", "Name"].

What I've tried dot notation and square bracket notation but neither worked.

<!-- row -->
<aura:iteration item="{!v.contacts} var="contact">
    <!-- column -->
    <aura:iteration item="{!v.fieldNames} var="fieldName">
        {!contact.fieldName} 
        {!contact[fieldName]}
    </aura:iteration>
</aura:iteration>

Not quite sure what is the correct approach to do this.

  • Jastin. you may need to create one more component. That will take object and field API and place this second component inside aura:iteration.. Basically in this second component use JAVSCRIPT to get the value from object like ex. obj[fieldapi] – Ratan Paul Jan 8 '16 at 5:30
14

As far as I can tell, Lightning components don't support that dynamic reference syntax.


You could consider dynamically generating the content of this component with the component controller:

Component

<aura:component controller="GetAFewContacts">
    <aura:attribute name="contacts" type="Contact[]" />
    <aura:attribute name="fieldNames" type="String[]" default='["Id","Name"]'/>
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    {!v.body}
</aura:component>

Client-side Controller

({
    doInit : function(component, event, helper) {
        var action = component.get("c.getContacts");
        action.setCallback(this,function(response){
                if (response.getState() === "SUCCESS"){
                    console.log(response.getReturnValue());
                    component.set("{!v.contacts}",response.getReturnValue());

                    var contacts = component.get("{!v.contacts}");
                    var fieldNames = component.get("{!v.fieldNames}");
                    var NewBody = "";
                    for (var i=0; i<contacts.length; i++){
                        for (var ii=0; ii<fieldNames.length; ii++){
                            NewBody += contacts[i][fieldNames[ii]];
                        }
                        NewBody += "\n";
                    }
                    console.log(NewBody);
                    $A.createComponent(
                        "ui:outputText",
                        {
                            "value" : NewBody
                        },
                        function(newComponent){
                            component.set("v.body",newComponent);
                        }
                    )
                }
            }
        );
        $A.enqueueAction(action);
    }
})

Server-side Controller

public class GetAFewContacts {

    @AuraEnabled
    public static list<Contact> getContacts(){
        return [SELECT Id, Name FROM Contact LIMIT 10];
    }

}

Or you could use a second component that sets the value through the component's renderer:

Component

<aura:component controller="GetAFewContacts">
    <aura:attribute name="contacts" type="Contact[]" />
    <aura:attribute name="fieldNames" type="String[]" default='["Id","Name"]'/>

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

    <aura:iteration items="{!v.contacts}" var="contact" >
        <aura:iteration items="{!v.fieldNames}" var="fieldName">

            <analysis:ContactAndFieldName contact="{!contact}" fieldName="{!fieldName}" />

        </aura:iteration>
    </aura:iteration>

</aura:component>

Client-side Controller

({
    doInit : function(component, event, helper) {
        var action = component.get("c.getContacts");
        action.setCallback(this,function(response){
                if (response.getState() === "SUCCESS"){
                    component.set("{!v.contacts}",response.getReturnValue());
                }
            }
        );
        $A.enqueueAction(action);
    }
})

Server-side Controller

public class GetAFewContacts {

    @AuraEnabled
    public static list<Contact> getContacts(){
        return [SELECT Id, Name FROM Contact LIMIT 10];
    }

}

Component -- ContactAndFieldName

<aura:component >
    <aura:attribute name="contact" type="Contact" />
    <aura:attribute name="fieldName" type="String" />

    <ui:outputText aura:Id="outputTextId" />

</aura:component>

ContactAndFieldNameRenderer

({

    render : function(component, helper) {
        var ret = this.superRender();

        var Contact = component.get('v.contact');
        var FieldName = component.get('v.fieldName');
        var outputText = component.find("outputTextId");
        outputText.set("v.value",Contact[FieldName]);

        return ret;
    },

})

If an init event is used instead of putting the javascript in the renderer:

Component -- ContactAndFieldName

<aura:component >
    <aura:attribute name="contact" type="Contact" />
    <aura:attribute name="fieldName" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

    <ui:outputText aura:Id="outputTextId" />

</aura:component>

ContactAndFieldNameController

({
    doInit : function(component, helper) {
        var Contact = component.get('v.contact');
        var FieldName = component.get('v.fieldName');
        var outputText = component.find("outputTextId");
        outputText.set("v.value",Contact[FieldName]);
    }
})

(no custom renderer, and everything else is the same)

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.