Drag drop between 2 diagrams

I have 2 diagrams,
each diagram has a different (complex) model.
I want to drag an object from one diagram to the other.
during the drop I need to transform the source model to the target model.
I tried to use the ExternalObjectsDropped, but I think it is too late because the object already added to the model (I use GraphLinksModel in both diagrams),
is there an example for that?
** one more thing, the model transformation happens in the server, so it is an async operation

what is the best way to handle that.

Set the Model.copyNodeDataFunction to a function that produces a new data object for the model with the properties that you want, based on the data that is provided as the first argument to the function. Hopefully you can recognize which model that the data is coming from and then decide how to handle to conversion to the target model’s data format.

For example:

<!DOCTYPE html>
<html><body>
  <div style="width: 100%; display: flex; flex-wrap: wrap">
    <div id="myDiagramDiv" style="border: solid 1px black; width:350px; height:300px; margin: 0 2px 0 0"></div>
    <div id="myDiagramDiv2" style="border: solid 1px black; width:350px; height:300px"></div>
  </div>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
// Since 2.2 you can also author concise templates with method chaining instead of GraphObject.make
// For details, see https://gojs.net/latest/intro/buildingObjects.html
const $ = go.GraphObject.make;  // for conciseness in defining templates

// ****** First Diagram ******

myDiagram = new go.Diagram("myDiagramDiv",
  {
    allowDragOut: true,
    "undoManager.isEnabled": true
  });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    $(go.Shape, "RoundedRectangle",
      { portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer", strokeWidth: 0 },
      new go.Binding("fill", "color")),
    $(go.TextBlock,
      { margin: 8 },
      new go.Binding("text", "key"))
  );

myDiagram.model = new go.GraphLinksModel(
  {
    nodeDataArray: [
      { key: "Alpha", color: "lightblue" },
      { key: "Beta", color: "orange" },
      { key: "Gamma", color: "lightgreen" },
      { key: "Delta", color: "pink" }
    ],
    linkDataArray: [
      { from: "Alpha", to: "Beta" },
      { from: "Alpha", to: "Gamma" },
      { from: "Beta", to: "Beta" },
      { from: "Gamma", to: "Delta" },
      { from: "Delta", to: "Alpha" }
    ],
    copyNodeDataFunction: (data, model) => {
      const copy = Object.assign({}, data);
      delete copy["__gohashid"];
      delete copy.key;
      if (typeof data.value === "number") {  // coming from Diagram/Model 2
        copy.color = "lightgray";
        copy.key = data.value;  // might be a duplicate of an existing key in model 1, but that's OK
        delete copy.value;
      }
      return copy;
    }
  });

// ****** Second Diagram ******

myDiagram2 = new go.Diagram("myDiagramDiv2",
  {
    allowDragOut: true,
    "undoManager.isEnabled": true
  });

myDiagram2.nodeTemplate =
  $(go.Node, "Vertical",
    $(go.Panel, "Spot",
      $(go.Shape, "Circle", { width: 40, height: 40, fill: "lightgray" }),
      $(go.TextBlock, { font: "8pt sans-serif" },
        new go.Binding("text", "value"))
    ),
    $(go.TextBlock, { editable: true },
      new go.Binding("text").makeTwoWay())
  );

// show a different model
myDiagram2.model = new go.GraphLinksModel(
  {
    nodeDataArray: [
      { key: 1, text: "Zeta", value: 1.23 },
      { key: 2, text: "Eta", value: 1.5 }
    ],
    linkDataArray: [
      { from: 1, to: 2 }
    ],
    copyNodeDataFunction: (data, model) => {
      const copy = Object.assign({}, data);
      delete copy["__gohashid"];
      delete copy.key;
      if (typeof data.color === "string") {  // coming from Diagram/Model 1
        copy.text = data.key;
        copy.value = 1.0;
        delete copy.color;
      }
      return copy;
    }
  });
  </script>
</body></html>

Remember that functions cannot be serialized into JSON-formatted text, so you have to make sure to set that functional property yourself.