Search code examples
google-drive-realtime-api

drive realtime api model toJson not populating fields in custom type


I'm building a Drive Realtime project using custom types: https://developers.google.com/google-apps/realtime/custom-objects.

I'm having an issue where the fields in my custom objects are not exported in the model.toJson() output. I'm sure I'm just missing something, but I haven't been able to find any differences with how I'm constructing the custom object vs. the realtime playground or the realtime API documentation.

Sample repro case using the realtime playground is below.

1) go to realtime playground: https://realtimeplayground.appspot.com/ 2) open developer console 3) Run the following code

test = function () {}
test.prototype = { init: function() { this.name = 'testName';}};
test.prototype.name = gapi.drive.realtime.custom.collaborativeField('name');
gapi.drive.realtime.custom.registerType(test, 'testType')
gapi.drive.realtime.custom.setInitializer(test, test.prototype.init);
var model = window.doc.getModel()
model.getRoot().set('myTest', model.create(test));
model.toJson()

observed output:

"{"id":"root","type":"Map","value":
  {"demo_string":
    {"id":"Tq50c9iybcXi","type":"EditableString","value":"Edit Me!"},
   "demo_list":{"id":"ZmjclOeUbcXj","type":"List","value":
     [{"json":"Cat"},{"json":"Dog"},{"json":"Sheep"},{"json":"Chicken"}]},
   "demo_cursors":{"id":"6TJ6Zzd2bcXj","type":"Map","value":{}},
   "demo_map":{"id":"ukRRMPHbbcXj","type":"Map","value":
     {"key1":{"json":"value 1"},"key2":{"json":"value 2"},"key3":{"json":"value 3"}}},
   "demo_custom":{"id":"44nsuMAPbcXk","type":"DemoMovie","value":
     {"name":{"json":"Minority Report"},
      "director":{"json":"Steven Spielberg"},
      "notes":{"json":""},"rating":{"json":""}}},
   "myTest":{"id":"Kq4hcV4UbcvW","type":"testType","value":{}}}}"

Expected:

"{"id":"root","type":"Map","value":
  {"demo_string":
    {"id":"Tq50c9iybcXi","type":"EditableString","value":"Edit Me!"},
   "demo_list":{"id":"ZmjclOeUbcXj","type":"List","value":
     [{"json":"Cat"},{"json":"Dog"},{"json":"Sheep"},{"json":"Chicken"}]},
   "demo_cursors":{"id":"6TJ6Zzd2bcXj","type":"Map","value":{}},
   "demo_map":{"id":"ukRRMPHbbcXj","type":"Map","value":
     {"key1":{"json":"value 1"},"key2":{"json":"value 2"},"key3":{"json":"value 3"}}},
   "demo_custom":{"id":"44nsuMAPbcXk","type":"DemoMovie","value":
     {"name":{"json":"Minority Report"},
      "director":{"json":"Steven Spielberg"},
      "notes":{"json":""},"rating":{"json":""}}},
   "myTest":{"id":"Kq4hcV4UbcvW","type":"testType","value":{"json":"testName"}}}}}"

Solution

  • Registering custom types can only occur during the "Pre-Load" phase of the document life cycle. Your code is correct, but is being executed on the document after the document has loaded. This causes the custom object to not be properly constructed, which is why it is lacking the JSON value that you have specified in the init function.

    To see the correct flow in action, put a break point on line 88 of static/elements/playground-app.js in the Realtime Playground application. Refresh the page and when execution has paused, run this code from the console:

    test = function () {}
    test.prototype = { init: function() { this.name = 'testName';}};
    test.prototype.name = gapi.drive.realtime.custom.collaborativeField('name');
    gapi.drive.realtime.custom.registerType(test, 'testType')
    gapi.drive.realtime.custom.setInitializer(test, test.prototype.init);
    

    Resume execution. When the application has fully loaded, run the rest of your code:

    var model = window.doc.getModel()
    model.getRoot().set('myTest', model.create(test));
    model.toJson()
    

    You will see that the outputted JSON matches what you are expecting:

    "myTest":{"id":"1OiQd2QoEqBs","type":"testType","value":{"name":{"json":"testName"}}}
    

    This workflow is documented under the "Registering custom types and fields" title of the Custom Collaborative Objects guide.