3

I'm working on making my lightning components compliant with Locker Service, and I see something strange happens with javascript variables after calling component.set() on them.

A component is having an attribute:

<aura:component controller="CPQ_QOT02_ConfigurationLC" access="GLOBAL">
    ...
   <aura:attribute name="item" type="Object" access="GLOBAL"/>
    ...
</aura:component>

In the init method of controller I'm calling server to fetch item variable. Item is a complex JS object having several properties (maps and arrays). Response from server is ok, I'm handling it in helper in below lines:

line   code

126    if (response.status == "SUCCESS") {
127        var item = JSON.parse(response.data);
128        console.log(item);
129        component.set("v.item", item);
130        console.log(component.get("v.item"));
131        ...

There is a significant difference between console.log that is printed to console in line 128 (before calling set) and in line 130 after calling it.

Here are snapshots from the browser console:

Console.log from line 128:

console.log from 128

Console.log from line 130 (after setter was called. Looks like all properties are not directly visible):

console.log from 130

As a result - whatever I would do later with the "v.item" variable - it seems not being applied to that attribute. Before locker service, everything was working fine, but also the result of both console.log's were the same.

Am I doing something wrong, or this is some framework issue?

1
  • did you find any solution for this issue? I activated the locker service today, and ohh boy, some weird stuff are happening! Thanks
    – RareFever
    Jul 27, 2017 at 11:59

1 Answer 1

3

This is definitely supposed to be a "feature" of Locker Service... an object stored in the framework becomes a "SecureObject" instead. Presumably this is designed to enable data binding to the view. But it is not documented particularly well.

Some things I have found:

  • Data binding to a JS object works slightly better if you declare the aura:attribute as a Map not an Object.
  • When you first component.set the Map it should contain all the keys it will ever have, otherwise newly added properties may not bind properly.
  • If you pass an object to another component and it tries to modify it and then bind to its own view, you may end up with trouble. Sometimes I find myself cloning objects passed from other components (i.e. using something as silly as JSON.parse(JSON.serialize(obj))).
5
  • Thank you for answer @Charles, so as I understand the only option to pass an object to another component and modify it there is this JSON.parse... If that's the case - I'm in a big trouble. Jun 30, 2016 at 15:28
  • I really am not sure how it works, I just know that when a JS object is set from one component and bound to another component which then tries to modify it, there is some trouble. I would like to hear more on this from the SF team.
    – Charles T
    Jun 30, 2016 at 15:47
  • Yes, yes, yes. If I could give you several upvotes, I would. I've spent the last week or so figuring out these kinds of things - they are not specified anywhere else!! Jun 30, 2016 at 22:32
  • A useful detail is that if you want to set the variable's default value to an empty object, you can use default="{}" but only if you've set the type to Map. If you set type to Object it will parse it as a string literal "{}". I should also add, if a variable will contain an array of JS Objects, then you can declare it as type Map[] for best results.
    – Charles T
    Jul 2, 2016 at 5:39
  • So summarizing, I can see that primitive types seem to be passed properly between parent & child components. Complex types not. If I remeber correctly, that's the other way around compared to Visualforce Components. Jul 4, 2016 at 13:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .