I am passing a list of SObjects with child relationships to a Lightning Web Component. If I query and pass my query results back to my LWC component directly, this works.
In Apex:
return [
SELECT Id, (SELECT Id, LastName FROM Contacts)
FROM Account
];
In LWC, I get a nice, nested JavaScript object:
[
{
Id: "0012D00000PDWKAQA5",
Contacts: {
Id: '0032D00000Ni9yZQAR',
LastName: 'Test'
}
},
...
]
Now I have a requirement that involves adding and removing child records before returning the response to my LWC component. But I'm noticing some weird behavior when I try to manipulate the child relationship, which I had assumed was just a List
type. When I use add()
, nothing is added. When I use remove()
, nothing is removed. And yet, no exception is thrown.
For example, you can run this in Execute Anonymous:
Account acc = [
SELECT Id, (SELECT Id, LastName FROM Contacts)
FROM Account
WHERE Id IN (SELECT AccountId FROM Contact)
LIMIT 1
];
Integer contactNum = acc.Contacts.size();
acc.Contacts.add(new Contact(LastName = 'Test'));
// THIS FAILS
System.assertEquals(contactNum + 1, acc.Contacts.size());
...or...
...
acc.Contacts.remove(0);
// THIS FAILS TOO
System.assertEquals(contactNum - 1, acc.Contacts.size());
I tried working around this by setting acc.Contacts
directly, e.g. acc.Contacts = new List<Contact>();
. This returns an exception: "Field is not writeable: Account.Contacts
"
Any help?
acc.Contacts
is, if not aList
, and whyadd()
andremove()
fail silently on whatever it is.acc.Contacts
is definitely aList
(verified usingacc.Contacts instanceOf List<Contact>
in your sample code), but looks like apex is treating it as immutable. By immutable, I mean the contacts list itself is read-only (or restricted for add/ remove) but fields within the retrieved contact records are writeable. I guess SF would have some strong reasons to do this, but couldn't find any SF documentation that explains about this.