Can’t access values of list attribute reference of dynamically create Lightning component

I am creating this Lightning component:

<aura:component>
  <aura:attribute name="record" type="Account" />
  <aura:attribute name="recordList" type="Account[]" />
   ...
</aura:component>

..dynamically using…

 $A.createComponent(
    "c:myComponent",
    {
        "record": cmp.getReference("v.account"),
        "recordList": cmp.getReference("v.accountList")
    },
);

I am perfectly able to access the single record but unable to access the record list.

myMethod: function(cmp) {
   cmp.get("v.record").Name = "Acme";  // Works

   for(var record of cmp.get("v.recordList")) {
      record.Name = "Acme";  // Fails
   }
}

Accessing the recordList fails with:

Uncaught Action failed: myComponent$controller$myMethod [Cannot add
property Name, object is not extensible]

When I console.log both attributes v.record is a Map representing an SObject but the recordList is an obfuscated “thing”

Proxy {0: XI, 1: XI, 2: XI, 3: XI, 4: XI, 5: XI, 6: XI, 7: XI, 8: XI, 9: XI, length: 10}
[[Handler]]
:
Object
[[Target]]
:
Array(10)
0
:
XI {path: Array(3), Ja: "v.recordList.a0246000005mfQzAAI", Kd: false, Ga: a, pb: a, …}

Strangely we could make it work by temporarily assigning/casting it to another attribute of type Account.

for(var record of cmp.get("v.recordList")) {
    cmp.set("v.tempRecord", record);

    var temp = cmp.get("v.tempRecord");
    temp[field] = number;
    cmp.set("v.tempRecord", temp);

    cmp.clearReference("v.tempRecord");
}

Why that? A bug? By design?

Answer

Seems to work fine on Winter 18 and Spring 18(upcoming) releases. Here’s the code I used to repro the issue.

Apex Controller

public with sharing class AccountController {
    @AuraEnabled
    public static List<Account> findAll() {
    return [SELECT id, name
            FROM Account
            LIMIT 50];
    }
}

App code

<aura:application controller="AccountController">
    <aura:attribute name="accounts" type="Account[]"/>
    <aura:attribute name="account" type="Account" />
     App
    <aura:handler name="init" value="{!this}" action="{!c.doInit}" />
    <c:containerCmp account="{!v.account}" accountList="{!v.accounts}"/>
</aura:application>

App Controller

({
    doInit: function(component, event) {
        var action = component.get("c.findAll");
        action.setCallback(this, function(a) {
            component.set("v.accounts", a.getReturnValue());
            component.set("v.account", a.getReturnValue()[0]);
        });
        $A.enqueueAction(action);
    }
})

c:containerCmp

<aura:component>
  <aura:attribute name="account" type="Account" />
  <aura:attribute name="accountList" type="Account[]" />
  <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    container cmp
    {!v.body}
</aura:component>

c:containerCmp controller

({
    doInit : function(cmp) {
        $A.createComponent(
            "c:myComponent",
            {
                "record": cmp.getReference("v.account"),
                "recordList": cmp.getReference("v.accountList")
            },
            function(newInnerCmp, status, errorMessage) {
                if (status === "SUCCESS") {
                    var body = cmp.get("v.body");
                    body.push(newInnerCmp);
                    cmp.set("v.body", body);
                }
            }
        );
    }
})

c:myComponent

<aura:component>
  <aura:attribute name="record" type="Account" />
  <aura:attribute name="recordList" type="Account[]" />
  <ui:button press="{!c.clickHandler}" label="Show account details"/>
  <br/>
  <aura:iteration items="{!v.recordList}" var="recordd">
      {!recordd.Id} : {!recordd.Name} <br/>
  </aura:iteration>
</aura:component>

c:myComponent controller

({
    clickHandler : function(cmp, event, helper) {
        cmp.get("v.record").Name = "Acme";  // Works
        for(var record of cmp.get("v.recordList")) {
            record.Name = "Acme";  // Suppose to fail here, but works fine
        }
        // Optional step to reflect the mutation in the UI
        // cmp.set("v.recordList", cmp.get("v.recordList"));
    }
})

Attribution
Source : Link , Question Author : Robert Sösemann , Answer Author : Ravi Jayaramappa

Leave a Comment