3

This is related to: Lightning Locker Service and object fields at different levels

But I thought it best to just give my example here rather than pollute someone else's thread.

I am seeing a similar issue with binding to object properties. My example is as follows.

ObjectTest.app:

<aura:application >
    <aura:attribute type="Object" name="data" access="GLOBAL" />
    <aura:attribute type="Object[]" name="datas" access="GLOBAL" />
    <aura:handler name="init" value="{!this}" action="{!c.init}" />

    <ui:inputText label="text field" value="{!v.data.value}" updateOn="keyup" />
    <ui:button label="Log it!" press="{!c.handle}" />
    <aura:iteration items="{!v.datas}" var="item" indexVar="index">
        <ui:inputText label="{! 'field ' + index}" value="{!item.value}">
        </ui:inputText>
    </aura:iteration>
</aura:application>

ObjectTestController.js:

({
    handle : function(c, e, h) {
        console.log(c.get('v.data'));
        console.log(c.get('v.data.value'));
        console.log(c.get('v.datas'));
        console.log(c.get('v.datas[0].value'));
    },
    init : function(c, e, h) {
        c.set("v.data", {});
        c.set("v.datas", [{value: 'hi'},{value: 'there'},{value: 'buddy'}]);
    }
})

The individual text field should update v.data.value on every keystroke but the data is not fetched or logged until you click the "Log it!" button. What you'll find is that no matter how many updates you make to the field, it will only fetch the data correctly the first time you press the button. Once you make an update after the first press, v.data gets frozen at the previous value. Interestingly, though, when you fetch v.data.value you get the updated one. This suggests that the text field is still bound to something but it's become disconnected from the original object.

Similarly I have an array of objects that is iterated in the UI to produce three text fields. If you edit the fields and click the button, you will see that the values are correctly logged in the v.datas object. However if you make another edit and click again, the v.datas object is frozen at the old values. Again, though, it's still bound to something because c.get('v.datas[0].value') appears to fetch the correctly updated value.

The fact that objects and arrays we store are being wrapped/unwrapped/filtered really needs to be explained in more depth in the Locker documentation. Prior to Locker we could trust that objects stored in components would consistently have reference equality and now it seems that they're being cloned and secured in ways that don't make intuitive sense.

  • Charles as you suspected its the same issue but additional data points are always appreciated – Doug Chasman Jun 15 '16 at 12:07
  • Thanks Doug. I am also running into an issue where if I get an object in the controller or helper, change a property and set it back, the view will not update after the first time. However if I reconstruct a brand new object and set it to the view attribute, the view refreshes. Is that a helpful data point too? – Charles T Jun 15 '16 at 17:46
  • Fix has been created and is making its way through the sausage factory now - targeted to deploy in the next available patch to Summer'16 which is scheduled for Tuesday/Wednesday – Doug Chasman Jun 16 '16 at 17:50
  • Thank you @DougChasman. I wrote in workarounds for two components that we are using regularly right now but I will hold off on the others and wait until the fix to see what works. – Charles T Jun 16 '16 at 18:02
  • In regards to the fix, one thing I hope will work properly again is binding to an object with custom getters and setters. In one case I iterate a bank of radio buttons from an array of objects and bind the value flag to an object property with a custom setter that records which actual button got pressed. – Charles T Jun 16 '16 at 18:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.