I have a struggle to understand something with Lightning here. Let me explain what I'm trying to do.
I have a component (let's call it ParentComponent
) which has one main attribute -> object with nested objects within - attributes. I'm using this list of attributes in aura:iteration
, where inside of it I'm using child lightning component (ChildComponent
) - I just want to separate piece of functionality into smaller bricks.
<aura:component controller="PrdConfigCls">
<aura:attribute name="paramProductId" type="String"/>
<aura:attribute name="product" type="PrdConfigCls.Product"/>
<aura:handler name="change" value="{!v.paramProductId}" action="{!c.paramProductIdChangeEventHandler}"/>
<aura:iteration items="{!v.product.attributes}" var="attr">
<c:ChildComponent attributeParam="{!attr}"/>
</aura:iteration>
</aura:component>
Now everything works fine when loading the component for the first time. ChildComponent
content properly renders attr
objects passed to it, for all elements in the Product.attributes
list.
But ParentComponent
have productId which may change. If this happens I'm using calling APEX class to reload second attribute -> Product
via standard mechanism:
ParentComponent
<aura:handler name="change" value="{!v.paramProductId}" action="{!c.paramProductIdChangeEventHandler}"/>
ParentComponentController
({
paramProductIdChangeEventHandler : function(component, event, helper) {
var paramProductId = component.get("v.paramProductId");
if (paramProductId != null && paramProductId != '') {
helper.loadProductConfiguration(component);
}
}
})
ParentComponentHelper
({
loadProductConfiguration : function(component) {
var action = component.get("c.getProjectProductDefinition");
action.setParams({ "projectProductId": component.get("v.paramProductId") });
var self = this;
action.setCallback(this, function(a) {
var productResp = a.getReturnValue();
var product = JSON.parse(productResp);
component.set("v.product", product);
});
$A.enqueueAction(action);
}
})
Now, because this happens Product
attribute in ParentController
is changing, new Product
have different list of Attributes
so I would want content of <aura:iterable>
to change - but unfortunately it doesn't happen. Instead I'm being left with a blank screen.
I tried to debug it and here is what happens (copied from chrome console)
1st change - loading the product for the first time:
-- Object {productDefinition: Object, product: Object, createComponentId: null, components: Array[2], attributes: Array[11]}
-- "ParentComponent": Done Rendering
-- 11x "ChildComponent": Done Rendering
2nd change - Done Rendering events are not happening - I only have output of console.log(product);
-- Object {productDefinition: Object, product: Object, createComponentId: null, components: Array[0], attributes: Array[21]}
Can you help me understand why it's not working? Maybe I'm just missing some rerender of child components?
I think I had this problem in the past when I discovered that attribute propagation to children works fine if you use Strings instead of complex types. It quite surprising to me, as in Visualforce Components it was totally opposite. I'm not very deep into how this works, but I think that in Visualforce Components attributes for complex types were passed through reference.
It would be great help if you can help me to understand this prior adding String serialization / deserialization magic.