1

I have related objects with a one-to-many relationship.

For example:

Owner1 ---> Thing1
Owner1 ---> thing2
Owner2 ---> Thing3

I want to display data from these objects in a table something like this:

Thing1.name | Thing1.thing | Thing1.Owner.name
Thing2.name | Thing2.thing | Thing2.Owner.name
Thing3.name | Thing3.thing | Thing3.Owner.name

I have two data structures -

thingArray = [Thing1, Thing2, Thing3];
ownerMap = {owner1.id :{owner1}, owner2.id : {owner2}};

Component:

<aura:component>
    <aura:attribute name="thingArray" type="List"/>
    <aura:attribute name="ownerMap" type="Map" />
    <!-- practice using aura iteration body and template properties -->
    <aura:iteration items="{! v.thingArray}" var="thing">
        {! thing.name } | {! thing.thing }| {! v.ownerMap[thing.Owner.Id].name } <br/>
    </aura:iteration>
</aura:component>

Which produces error:

expecting a positive integer, found 'item' at column 10 of expression: ownerMap[item]

I've created an additional component which displays this data:

component mapReader.cmp:

<aura:component>
    <aura:handler name="change" value="{! v.bigMap }" action="{! c.setStuff }" />
    <aura:attribute name="bigMap" type="Map"/>
    <aura:attribute name="bigKey" type="String"/>
    <aura:attribute name="littleKey" type="String"/>
    <aura:attribute name="littleKey2" type="String"/>
    <aura:attribute name="littleKey3" type="String"/> 
    <aura:attribute name="displayValue" type="String"/>
    {! v.displayValue }
</aura:component>

Controller mapReader.js:

({
    setStuff : function(component, event, helper) {
        let bigMap = component.get('v.bigMap');
        let bigKey = component.get('v.bigKey');
        let littleKey = component.get('v.littleKey');
        let littleKey2 = component.get('v.littleKey2');
        let littleKey3 = component.get('v.littleKey3');
        //Set values depending on which keys are available
        let value;
        if(littleKey2){
            if(littleKey3){
                value = bigMap[bigKey][littleKey][littleKey2][littleKey3];
            }else{
                value = bigMap[bigKey][littleKey][littleKey2];
            }
        }else{
            value = bigMap[bigKey][littleKey];
        }
        component.set("v.displayValue", value);
    }
})

I then use it like this:

<aura:component>
    <aura:attribute name="thingArray" type="List"/>
    <aura:attribute name="ownerMap" type="Map" />
    <!-- practice using aura iteration body and template properties -->
    <aura:iteration items="{! v.thingArray}" var="thing">
        {! thing.name } | {! thing.thing }| <c:mapReader bigMap="{! v.ownerMap}" bigKey="{! thing.OwnerId }" /><br/>
    </aura:iteration>
</aura:component>

This works fine to display on initial render.

PROBLEM

I need to be able to update the list, change order - when the thingArray gets updated the child mapReader components don't seem to get created.

It seems like it should be a simple thing to read a value from an object/map - what is the easiest way of doing this?

I really want to keep the data structure (array + map) as is, because the above is a massive simplification of requirements and there all kinds of reasons why pushing them all into the same data structure is going to be a massive headache and require a load of extra code (for example, I need to retrieve two sets of similar data using completely different criteria on different objects, and retrieve related lists from parent objects).

Edit: also... ideally I don't really want to put the table into a separate component and trigger re-render/ re-render the entire component to re display the child component, because in fact I have two tables that need to be able to interact and various other data on the parent component.

1 Answer 1

1

I see this asked a lot. The Aura framework does not handle this syntax currently:

{!Object[propertyName].value}

What you will have to do is use another component / controller to perform this functionality like this answer Is there a way to access object properties in Lightning expressions

5
  • I have actually created such a component - the problem is that this child component doesn't render when the array being iterated through is updated - so if I change the order of the items in the 'thingArray' - the display updates but the parts output by the child mapreader component disappears.
    – eaeaoo
    Jan 15, 2020 at 14:18
  • Can you edit your question to show the use of that component? Jan 15, 2020 at 14:20
  • It's already on there - towards the bottom.
    – eaeaoo
    Jan 15, 2020 at 14:21
  • 1
    So the one thing I see, you are detecting a change on bigMap in your child component which is tied to the ownerMap on the parent component, but if you changing thingArray it will not detect a change because that is tied to the bigKey attribute in your child component Jan 15, 2020 at 14:26
  • 1
    Yep - that was it - I added in an init handler and it works fine. Thanks!
    – eaeaoo
    Jan 16, 2020 at 9:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .