3

We have a lightning component that is initialized with an SObject from Apex. It then allows the user to make some changes to that SObject and send it back to Apex in another method for some processing. In the initial query for the object we include some related data that is required from our controller (for example, Owner.Name). If we send the SObject back to our Apex method with the related object still populated we get an error from the server:

Unable to read SObject

Previously, we had worked around this by executing the following prior to sending the record back to Apex:

delete sObject.Owner;

The Apex method returns an updated version of the record with the related data back in there so there was no issue. However, after enabling Locker Service we are getting the following error when trying to delete the related data:

Cannot delete property 'Owner' of [object Object]

Is this by design? If so, Why would we be unable to modify objects that we created in this way? If we cannot delete object values and the fields on our objects are dynamic, what is the best practice for avoiding the "Unable to read SObject" error when our objects contain dynamic related data?

** Update **

I have narrowed the problem down further. The "Unable to read SObject" error only occurs when the object coming from Apex was initialized with SObjectType.newInstance() after a result was not found via SOQL. This is also causing another issue where we are unable to populate fields on the record that did not initially have default values. I can see that the framework did not create get() and set() properties for most of the fields that we are then allowing users to populate in the UI. This results in the lightning:input fields not being bound to the record correctly and no data being set.

2
  • 1
    I'm experiencing Cannot delete property 'Owner' of [object Object] issue too from yesterday. – Praveen Mar 11 '17 at 5:12
  • I am going to spin off the SObjectType.newInstance() issue into a separate question. – dsharrison Mar 13 '17 at 23:18
1

You could always clone the object omitting the attributes you don't want, and pass the clone to your Apex controller update method. For example:

var contact = {Id: sobject.Id, FirstName: sobject.FirstName};
var action = component.get("c.updateContact");
action.setParams({
    "myContact": contact,
});

Note that deleting attributes of regular objects (not sObjects) works. In the example above you could do:

delete contact.firstName;

That said, I'm able to send back an object with related data (like Owner) to an update function in my Apex controller without getting the "Unable to read sObject" error you are getting. Here is a simple example that works for me:

Apex Controller:

global with sharing class ContactController {

    @AuraEnabled
    public static Contact findContact() {
        return [SELECT id, FirstName, Owner.Name FROM Contact LIMIT 1];
    }

    @AuraEnabled
    public static Contact updateContact(Contact myContact) {
        update myContact;
        return myContact;
    }
}

Component controller:

({
    findItem : function(component, event, helper) {
        var action = component.get("c.findContact");
        action.setCallback(this, function(a) {
            var result = a.getReturnValue();
            component.set("v.contact", result);
        });
        $A.enqueueAction(action);
    },

    updateItem : function(component, event, helper) {
        var contact = component.get("v.contact");
        var action = component.get("c.updateContact");
        action.setParams({
            "myContact": contact,
        });
        action.setCallback(this, function(a) {
            var result = a.getReturnValue();
            component.set("v.contact", result);
        });
        $A.enqueueAction(action);

    }
})
3
  • Thanks for providing the example. Copying is not really ideal for us because our request includes dynamic fields. I will check to see if we have access to all the properties we would need (like a reliable typeof) to do a dynamic copy. I will have to dig into why we are getting the error during the Apex parameter deserialization and you are not. We do have a number of additional relationships that I omitted from my original question for brevity. – dsharrison Mar 13 '17 at 16:57
  • You should be fine with dynamic properties if you just go var obj = JSON.parse(JSON.stringify(sobject));. This will make you a brand new object with all the required properties. If you got any further issues, you could put in an intermediate step and remove the "sobjectType":"sObject", part of the string before parsing again. – Caspar Harmer Mar 28 '17 at 20:36
  • Or you could do something like this: for(var k in firstObject) { if (k != 'sobjectType' ) {secondObject[k]=firstObject[k];}} – Caspar Harmer Mar 28 '17 at 20:37
1

The deletion of object properties issue has been corrected in Summer'17. I do not know if the fix is planned to be backported to Spring'17 at this time.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.