1

I'm facing a really strange issue

I have an attribute defined in my lightning component:

<aura:attribute name="item" type="Object"/>

This object is fetched from server in the init call with a pretty standard mechanism:

Controller code:

helper.loadItem(component)

Helper code:

loadItem : function(component) {

    var actionItem = component.get("c.getQuoteItem");
    actionItem.setParams({ "quoteItemId": component.get("v.itemId") });
    var self = this;

    actionItem.setCallback(this, function(a) {
        var state = a.getState();
        if (state === "SUCCESS") {
            var response = JSON.parse(a.getReturnValue());

            if (response.status == "SUCCESS") {
                var item = JSON.parse(response.data);
                this.setInitialAttributeValues(component, item);
                component.set("v.item", item);
            } else if (response.status == "ERROR") {
                ...
            }
        ...
     }

item object is quite complex object with multiple nested objects as properties. Especially item.attributes is an object that is a map of objects like below:

item.attributes.ATR_TESTATTRIBUTE_ = {attributeValue: {value: 'test'}, ...}
item.attributes.ATR_NAMEOFOTHERATTRIBUTE_ = {...}

These map of item.attributes map does not usually come from server, but is initialized in this.setInitialAttributeValues(component, item); method in helper (just after getting data from server, but before calling first component.set).

After having Locker Service turned on I can see that not all of them are being converted to secure objects, therefore they are not visible to the application at later stages.

This is how item looks as secure object - top level looks good. Triple dots mean getters and setters were properly initialised:

This is how secure object - top level looks like. Triple dots mean getters and setters were properly initialised

But if I expand attributes property - nested objects don't have any getters and setters (no triple dots). They're just plain objects. Therefore they behave like they are not visible to the application in further methods.

Expanded attributes property

I tried different workarounds I heard in the past - here like calling JSON.parse(JSON.stringify()) but it doesn't seem to work. Any idea what may be happening?

EDIT - NARROWED DOWN SCENARIO

I have created a narrowed scenario of that problem and it seems that framework has problem with adding new properties to existing variables. Example below:

Apex Class: XXX_MASIM_TestLockerLC

public with sharing class XXX_MASIM_TestLockerLC {

    @auraEnabled
    public static String getObjWrapper() {
        ObjWrapper result = new ObjWrapper();
        result.name = 'test';
        result.attributes = new Map<String, SubObjWrapper>();
        result.attributes.put('ATR_ATR1_', new SubObjWrapper('test', 'test'));
        result.attributes.put('ATR_ATR2_', new SubObjWrapper('test2', 'test2'));
        return JSON.serialize(result);
    }

    public class ObjWrapper {
        public String name {get;set;}
        public Map<String, SubObjWrapper> attributes {get;set;}
    }

    public class SubObjWrapper {
        public String label {get;set;}
        public String value {get;set;}

        public SubObjWrapper(String label, String value) {
            this.label = label;
            this.value = value;
        }
    }

}

Component

<aura:component controller="XXX_MASIM_TestLockerLC">
    <aura:attribute name="testObj" type="Object"/>
    <aura:handler name="init" value="{!this}" action="{!c.initialize}"/>
</aura:component>

Component Controller

({
    initialize : function(component, event, helper) {
        helper.loadObjWrapper(component);
    }
})

Component Helper

loadObjWrapper function is responsible for fetching object from server. Before calling component.set it passes the object through another helper function to add additional properties

({
    loadObjWrapper : function(component) {
        var actionItem = component.get("c.getObjWrapper");
        var self = this;

        actionItem.setCallback(this, function(a) {
            var state = a.getState();

            if (state === "SUCCESS") {
                var testObj = JSON.parse(a.getReturnValue());
                console.log(testObj);
                this.addAdditionalAttributes(component, testObj);
                component.set("v.testObj", testObj);
                console.log(component.get("v.testObj"));
            }
        });
        $A.enqueueAction(actionItem);
    },

    addAdditionalAttributes : function(component, item) {
        var placeholder1 = {'name': 'test3', 'value': 'test3'};
        var placeholder2 = {'name': 'test4', 'value': 'test4'};

        item.attributes['ATR_ATR3_'] = placeholder1;
        item.attributes['ATR_ATR4_'] = placeholder2;

        console.log(item);
    }
})

When I console.log the object it looks like properties were only properly converted to secure object for those properties that came from server. Properties that were added by addAdditionalAttributes function are not properly converted to Secure Object - they don't have getters and setters.

Properties that were not converted to Secure Object

Case number: #16215426

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.