Another issue that I found with locker service, I presume this is some kind of framework bug related to locker service (if someone can tell, I'd appreciate).
I have a simple component which has one attribute - item
, which has one property errors
that is array of objects. In the component I display errors using aura:iteration
.
The problem happens when I will modify item.errors
(in this example after calling rerender
controller function.
In the console.log
I can see the array has 3 elements (which is correct):
But on the screen I can see only one element being rendered:
Component code:
<aura:component >
<aura:attribute name="item" type="Object" access="global"/>
<aura:handler name="init" value="{!this}" action="{!c.initialize}"/>
<h1>This is sample component to show problem of aura:iteration and binding of attributes</h1>
<a onclick="{!c.rerender}">RERENDER</a>
<aura:if isTrue="{!v.item != null}">
<span>
<aura:iteration items="{!v.item.errors}" var="err">
<span>
<aura:if isTrue="{!err.display}">
<div>{!err.message}</div>
</aura:if>
</span>
</aura:iteration>
</span>
</aura:if>
</aura:component>
Controller Code:
({
initialize : function(component, event, helper) {
var item = {};
var errs = [];
var err1 = {};
err1.display = true;
err1.message = 'test error';
errs.push(err1);
item.errors = errs;
component.set("v.item", item);
},
rerender : function(component, event, helper) {
var item = component.get("v.item");
item.errors = [];
var err1 = {};
err1.display = true;
err1.message = 'test error';
item.errors.push(err1);
var err2 = {};
err2.display = true;
err2.message = 'test error 2';
item.errors.push(err2);
var err3 = {};
err3.display = true;
err3.message = 'test error 3';
item.errors.push(err3);
component.set("v.item", item);
console.log(component.get("v.item"));
}
})
EDIT: I suspect that it may come from the fact that newly added array elements were not wrapped into secure object (only 1st item was wrapped, 2nd and 3rd were not)?
EDIT 2: This doesn't happen when you iterate over an object[]
attribute directly. In that case everything works as expected. The problem only happens when you iterate over a collection that is a property of some object:
This would work fine:
<aura:attribute name="errors" type="Object[]" access="global"/>
<aura:iteration items="{!v.errors}" var="err" indexVar="i">
<span>
<aura:if isTrue="{!err.display}">
<div>{!err.message}</div>
</aura:if>
</span>
</aura:iteration>