[SalesForce] Refresh child component based on parent onchange value within nested aura iteration

Parent component :

<tbody>
    <aura:iteration items="{!v.WrapperObj.plannedEffortInnerObjList}" var="item" indexVar="index">  
        <tr>

            <aura:iteration items="{!item.plannedEffortObjList}" var="items" indexVar="Index">
               <td>
                    <aura:if isTrue="{!items.Is_Editable__c}"> 
                        <lightning:input type="number" default="0" aura:id="effortId" value="{!items.Allocated_Hours__c}" 
                                         onchange="{!c.calculateTotalhrs}" name="String" min="0"  />
                          <aura:set attribute="else">
                            <ui:outputText value="{!items.Allocated_Hours__c}" />
                        </aura:set>
                    </aura:if> 
               </td>
            </aura:iteration>
            <td> 
          <c:mycloudian_Lightning_PMODetails_InnerComponent  totalHoursList="{!v.totalHours}" index="{!index}"/>    
              <!-- <ui:outputText  aura:id="textv" value="{!v.totalHours[0]}" />-->
            </td>
        </tr>
    </aura:iteration> 
</tbody>

Parent Controller:

calculateTotalhrs: function(component, event, helper) { var totalHours = [];
    var stringifyVal = JSON.stringify(component.get('v.WrapperObj'));
    var parsed = JSON.parse(stringifyVal);
    var innerObjectList = JSON.stringify(parsed.plannedEffortInnerObjList);
    var parsedInnerObjectList = JSON.parse(innerObjectList);
    for (var i = 0; i < parsedInnerObjectList.length; i++) {
        var plannedEffortObjList = JSON.stringify(parsedInnerObjectList[i].plannedEffortObjList);
        var parsedPlannedEffortObjList = JSON.parse(plannedEffortObjList);
        var totalHrs = 0;
        for (var j = 0; j < parsedPlannedEffortObjList.length; j++) {
            var counter = JSON.stringify(parsedPlannedEffortObjList[j]);
            var counterParsed = JSON.parse(counter);
            if (typeof counterParsed.Allocated_Hours__c !== 'undefined') {
                totalHrs = parseInt(totalHrs) + parseInt(counterParsed.Allocated_Hours__c);
            }
        }
        totalHours.push(totalHrs);

    }
    console.log('totalHrs---------------', totalHours);
      component.set("v.totalHours", totalHours);
},

enter image description here

onchange="{!c.calculateTotalhrs}" I'm calculating total hours and pushing back to v.totalHours variable.

First time it works fine as shown in the picture but onchange, total hours value is not refreshing (child component c:mycloudian_Lightning_PMODetails_InnerComponent is not refreshing the new values).

I have tried this reference link solution but not working due to calling child component within nested aura:iteration -> https://developer.salesforce.com/blogs/developer-relations/2017/04/lightning-inter-component-communication-patterns.html

Child Component :

<aura:component >
    <aura:attribute name="totalHoursList" type="Integer[]"  />
    <aura:attribute name="index" type="string" />
    <aura:attribute name="value" type="String" />
        <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    {!v.value}
</aura:component>

Child Controller :

doInit : function(component,event,helper) {
    var totalHoursList = component.get('v.totalHoursList');
    var index = component.get('v.index');
    component.set('v.value', totalHoursList[index]);   
},

any help would be greatly appreciated

Best Answer

You're only grabbing the value upon initialization. Instead, you may want to also listen for any changes to the data:

<aura:component >
    <aura:attribute name="totalHoursList" type="Integer[]"  />
    <aura:attribute name="index" type="string" />
    <aura:attribute name="value" type="String" />
    <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
    <aura:handler name="change" value="{!v.totalHoursList}" action="{!c.doInit}"/>
    {!v.value}
</aura:component>

You might want to rename the function, since you're doing more than just initialization at this point, but it should help you get started.