This API was turned down in January 2019 and is deprecated. Migrate to Cloud Firestore or another data store.

Listening for Realtime events

Whenever a data model object is modified, either by the local client or by another collaborator, an event describing the change is fired.

All changes to collaborative objects, such as modifying a string, collection, or custom type, emit events. Because changes can originate from either the local application or a remote collaborator, it is important that applications properly listen for and respond to these events to keep the view in sync with the model.

The type of event that is fired depends on the collaborative object that was modified and what change was made to it. For example, adding a value to a string will fire a TextInsertedEvent.

For details about event types, see the EventType enum in the API reference.

Event dispatching

Events are dispatched after the completion of the current synchronous block rather than executed immediately. This ensures all changes to the model are applied prior to executing the event handlers. Consider the following example.

var onValueAdded = function(event) {
  console.log("Items added", event.values);
};

var list = model.createList();
list.addEventListener(gapi.drive.realtime.EventType.VALUES_ADDED, onValueAdded);

console.log("Adding item 1");
list.push("Hello");
console.log("Adding item 2");
list.push("World");

The console for the current collaborator will show:

Adding item 1
Adding item 2
Items added, ["Hello"]
Items added, ["World"]

To ensure the same happens for events from remote collaborators, applications should mark the boundaries of dependant operations using Model.beginCompoundOperation() and Model.endCompoundOperation(). See Build a Data Model for more information on compound events.

model.beginCompoundOperation();
var list = model.createList();
list.push("Hello");
list.push("World");
model.endCompoundOperation();

Compound operations do not follow traditional transaction behaviors, particularly with regard to read and write isolation. They do, however, ensure that dependent changes are both transmitted and received together. All events for changes that occur within a compound operation are emitted after all of the changes are applied to the model.

Event bubbling

Most events are emitted on the specific object that changed and do not bubble. There is one exception: the ObjectChangedEvent is a bubbling event that is additionally emitted for every change. The ObjectChangedEvent is sent to the object that changed and all of its ancestors. One ObjectChangedEvent is emitted for every object that changed within a compound operation. The specific changes are described in the events field.

ObjectChangedEvent is not as specific as other events, but can simplify management of event listeners when using MVC frameworks that have other mechanisms for detecting changes. For example, an ObjectChangedEvent listener added to the root will be informed whenever any change is made in any part of the model.

function displayObjectChangedEvent(evt) {
  var events = evt.events;
  var eventCount = evt.events.length;
  for (var i = 0; i < eventCount; i++) {
    console.log('Event type: '  + events[i].type);
    console.log('Local event: ' + events[i].isLocal);
    console.log('User ID: '     + events[i].userId);
    console.log('Session ID: '  + events[i].sessionId);
}

doc.getModel().getRoot().addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED, displayObjectChangedEvent);

All other collaborative events do not bubble through the model. Only listeners that are attached directly to the modified object are executed.

Local vs. remote events

All events include a property isLocal which can be used to check if the event originated locally. If your application is applying local view changes directly, instead of in response to a collaborative object event, any event handlers should check the source of the event to avoid applying local changes multiple times.

function filterLocalEvents(evt) {
  var isLocal = evt.isLocal;
  if (!isLocal) {
    console.log("Non-local event.");
    //Insert UI update code here.
  }
  else {
    console.log("Local event.");
  }
}

Document events

Some events that are not specific to the model are emitted on the Document.

Collaborator events

Collaborators are other users that are currently viewing the document. CollaboratorJoinedEvent and CollaboratorLeftEvent are emitted in response to users respectively loading and closing the current document. Listeners for these events are attached to the document, not the model.

function displayCollaboratorEvent(evt) {
  var user = evt.collaborator;
  console.log('User ID:'    + user.userId);
  console.log('Session ID:' + user.sessionId);
  console.log('Name:'       + user.displayName);
  console.log('Color:'      + user.color);
}

document.addEventListener(gapi.drive.realtime.EventType.COLLABORATOR_JOINED, displayCollaboratorEvent);

You can retrieve the current list of active collaborators by calling document.getCollaborators(). The collaborator representing the current session is identified by the isMe property.

function displayAllCollaborators(document) {
  var collaborators = document.getCollaborators();
  var collaboratorCount = collaborators.length;
  console.log(collaboratorCount + ' collaborators:');
  for (var i = 0; i < collaboratorCount; i++) {
    var user = collaborators[i];
    console.log('Name: ' + user.displayName);
    console.log('Is me:' + user.isMe);
  }
}

The document save state indicates when there are pending changes that have not yet been saved on the server. You can use the DocumentSaveStateChangedEvent to track when document is fully saved.

Undo and redo state events

The Realtime API tracks local changes to the collaborative model that can be undone or redone. The Realtime stores this state in the canUndo and canRedo properties of the model. When either of these properties changes state, the model emits a UndoRedoStateChangedEvent. This even can be used for updating UI elements such as undo or redo buttons, as outlined in the following code sample.

function onUndoStateChanged(evt) {
  if (evt.canUndo) {
    console.log("Events available to undo.");
    //Code to enable UI undo button.
  }
  else {
    console.log("No events to undo.");
    //Code to disable UI undo button.
  }
  if (evt.canRedo) {
    console.log("Events available to redo.");
    //Code to enable UI redo button.
  }
  else {
    console.log("No events to redo.");
    //Code to disable UI redo button.
  }
}

model.addEventListener(gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED, onUndoStateChanged);

This sample illustrates attaching an event listener to the model with a callback that tests for canUndo and canRedo in order to update UI elements.

Skicka feedback om ...

Behöver du hjälp? Besök vår supportsida.