4

Not sure if its a bug or a misunderstanding of how things are meant to work:

  • disable single instance mode
  • Create a new parse object (or query one from the server) and populate properties
  • Make a copy of the object (e.g. if you were editing the properties on a form and wanted the option to save/discard changes)
  • Copy is empty ....

using parse-js-sdk 1.9.2 and angular 1.4.8

  //comment out the following line and it works ok
  Parse.Object.disableSingleInstance();

  var parseObjClass = Parse.Object.extend('Comments', {
            // Instance methods
            initialize: function (attrs, options) {}
        },
        {});

        ['name', 'desc'].forEach(function (item) {

        Object.defineProperty(parseObjClass.prototype, item, {
            get: function () {
                return this.get(item);
            },
            set: function (aValue) {
                return this.set(item, aValue);
            }
        });
    });

  var parseObj = new parseObjClass();
    parseObj.name = 'Hello World'
    parseObj.desc = 'Test Object'

  console.log('original is ' + JSON.stringify(parseObj)); 
  //--> original is {"name":"Hello World","desc":"Test Object"}

  var objCopy = angular.copy(parseObj);

  console.log('copy is ' + JSON.stringify(objCopy));
  //--> copy is {}

Here is a plunker illustrating https://plnkr.co/edit/UjWe9dl6D6Qkx9ihBSMC

background : we are using disableSingleInstance mode because we have a mobile app and a a web app that can interact with the same database rows (timesheet data) and were having problems with the js-sdk not always having the latest version of the data...

10
  • your parseObj doesn't contain name or desc while logging original.. not sure how Parse object works though Commented Apr 24, 2017 at 7:40
  • updated code snippet to include the full parseObjClass code as per the plunker Commented Apr 24, 2017 at 8:04
  • Disabling Single Instance means you'll be able to have separate instances of objects that are supposedly the same object, and updating one will not update the other. I feel like for your problem, you'd prefer to keep Single Instance enabled. This doesn't mean there can only be one reference across your whole app. It means that on that individual server, any reference to a ParseObject of that class with that Id will have the same data as it is updated. Commented Apr 26, 2017 at 20:53
  • I ran into a lot of not having the latest data issues due to a misunderstanding of how fetchIfNeeded works. I had thought it would fetch data if there was new data on the server. However, it actually only fetches if you have a shell of an object (i.e. pointer field on an object returned by a query, and you didn't call include.field), that hasn't been fetched at all. Once an object is fetched at all, fetchIfNeeded will never fetch the object again (that specific instance, not a new instance with the same id). Commented Apr 26, 2017 at 20:54
  • As for your particular issue with your code, I imagine that Parse Objects aren't compatible with this Angular method. Write your own function that creates a new Parse Object with the same className as the one you want to copy, and iterates all of its keys to copy its data, if you'd like a separate instance that is a "copy". You may need to write a separate function for each of your Parse Classes to make sure each key is properly copied over. Commented Apr 26, 2017 at 20:56

1 Answer 1

3
+25

According to angular.copy(source, [destination]); docs:

Only enumerable properties are taken into account. Non-enumerable properties (both on source and on destination) will be ignored.

And according to MDN docs for Object.defineProperty(obj, prop, descriptor):

When defining properties like that by default, it's not enumerable. Therefore you have to specify enumerable: true on the descriptor.

For example:

Object.defineProperty(parseObjClass.prototype, item, {
    enumerable: true,
    get: function () {
        return this.get(item);
    },
    set: function (aValue) {
        return this.set(item, aValue);
    }
});

UPDATE

Just realised that there are a problem with your setter and the getter the way you are using it are preventing your property of being an enumerable. You can remove the get and set and replace with a writable and it should be fine.

Object.defineProperty(parseObjClass.prototype, item, {
    enumerable: true,
    writable: true
});

If you need to use get and set you have to use a private var or something to intermediate, like get: () => _props[item];

Sign up to request clarification or add additional context in comments.

2 Comments

this answer looked very promising, but alas after adding enumerable : true it still doesn't work : plunker
Again, I was excited with the proposed solution, but for some reason if i set writeable:true to the prototype definition, I can't even assign the object property in the first place (i.e. the first console.log shows an object value of {})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.