3

I'm trying reference data changes that occurred on child components from my parent component. From the Lightning documentation, it sounds like a two-way data binding will occur as long as long as I use the {!} syntax.

This works fine except when I iterate through a list. For instance:

Parent Component:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" >
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    <aura:attribute name="listOfChilds" type="List" />
    <aura:attribute name="barString" type="String" default="bar"/>


    <lightning:button label="Save" onclick="{!c.onClick}"/>

    <c:testChild child="{!v.barString}" />

    <ul>
        <aura:iteration items="{!v.listOfChilds}" var="item">
            <li>
                <c:testChild child="{!item}" />
            </li>
        </aura:iteration>
    </ul>

</aura:component>

Parent Controller:

({
    init : function(component, event, helper) {
        component.set('v.listOfChilds', ['bar','bar','bar']);
    },
    onClick : function(component, event, helper) {
        console.log(component.get('v.listOfChilds'));
        console.log(component.get('v.barString'));
    }
})

Child component:

<aura:component>
    <aura:attribute name="child" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    {!v.child}
</aura:component>   

Child controller:

({
    init : function(component, event, helper) {
        component.set('v.child', 'foo');
    }
})

In this example, hitting my button on the parent component will output: ['bar','bar','bar'] for the list AND 'foo' for the barString. Both values are modified by the child components but the binding only occurs for the non-iterated values.

Anyone know how I can still achieve databinding with the parent when updating list items?

  • Do all those bindings need to be two-way? You might consider using one-way bindings where possible {#}. – Adrian Larson Feb 13 '18 at 0:58
  • @AdrianLarson, the bindings don't necessarily need to be two-way but changes to the child components need to be referenced from the parent. I tested the code with {#} and I get the same result – Matthew Mitchener Feb 13 '18 at 1:02
2

So after some additional tests, it appears it is not possible to bind attributes in an iterable (v42.0). Meaning {!item} is the same as {#item}.

However, you can still pass in attributes from outside the scope of the iteration. So my workaround is to store the changes to the list items in temp or copy list (using the same iterable list, will cause issues since the child components have no way to reference the parent).

So the parent component will look like this:

<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes" access="global" >
    <aura:handler name="init" value="{!this}" action="{!c.init}" />
    <aura:attribute name="listOfChilds" type="List" default="[]"/>
    <aura:attribute name="listCopy" type="List" default="[]"/>
<lightning:button label="Check" onclick="{!c.onClick}"/>

<ul>
    <aura:iteration items="{!v.listOfChilds}" var="item" indexVar="index">
        <li>
            <c:testChild listOfChilds="{!v.listCopy}" child="{!item}" index="{!index}"/>
        </li>
    </aura:iteration>
</ul>

Then in the child controller, you can create a handler to update the push changes to the temp or copy list.

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.