Client-server roundtrips during diagram editing

dear Walter, thank you very much for your assistance. based on your advices i managed to implement all the necessary client-server roundtrips. i’m summarizing my solution here:

i adopted the optimistic strategy: client displays an estimated outcome until server returns the full resulting status, then i update the client view.

client-server calls are implemented in the addModelChangedListener hook, monitoring evt.isTransactionFinished flag as described here:

in order to make transactions work, i had to enable the undo manager, but as i don’t actually need the undo functionality, i have disabled the function on the diagram:

this.goDiagram.undoManager.isEnabled = true;
this.goDiagram.allowUndo = false;

in addModelChangedListener, i’m performing my server-client async calls when detecting the following transactions:

      this.goDiagram.addModelChangedListener((evt: go.ChangedEvent) => {
         if (!evt.isTransactionFinished) return;
         var txn = evt.object as go.Transaction;  // a Transaction
         if (txn === null) return;

         if (txn.name == "Linking") {/*async call to server*/}
         else if (txn.name == "Delete") {/*async call to server*/}
         else if (txn.name == "Move") {/*async call to server*/}
         ...
      }

in case i need, i can analyze the underlying changes using:

         txn.changes.each((change: go.ChangedEvent) => {
            if (change.modelChange) {/*analyze underlying change*/}
         });

in order to be able to react on the event when the user applies a new layout (digraph or force directed), i have wrapped the code that sets the new layout in a transaction:

      this.goDiagram.startTransaction("SetLayout");
      this.goDiagram.layout = /*new layout to be applied*/;
      this.goDiagram.commitTransaction("SetLayout");

after doing that i could also weave my client-server call into addModelChangedListener:

      this.goDiagram.addModelChangedListener((evt: go.ChangedEvent) => {
         if (!evt.isTransactionFinished) return;
         var txn = evt.object as go.Transaction;  // a Transaction
         if (txn === null) return;
         ...
         if (txn.name == "SetLayout") {/*async call to server*/}
         ...
      }

i’m satisfied with the resulting behavior.
but please, let me know if you see any flaws or possible improvements to the above.