ExternalObjectsDropped does not send me the node that is dragged, instead it shows me the link

ExternalObjectsDropped does not send me the node that is dragged, instead it shows me the link,

if you look at the picture below

image

I am dragging the node from one diagram to another,
then on the other diagram I am listening to the ExternalObjectsDropped event like this

onExternalObjectsDropped(event: DiagramEvent) {
event.subject.toArray().forEach(values=>{
console.log(“val”, values);
})
}

the value that I get in the array is of the link and not of the node.
how can I get the node value?

for now I did this workaround but it does not look nice

        if (node?.data?.from) {
            node = this.diagram.findNodeForKey(node.data.from);
        }

I am reading the link data, and finding the node in the diagram.
is there a better way?

When I make sure that the Palette (i.e. source Diagram) has a node with a reflexive link connected, and I drag that into the main (target) Diagram, I find that the “ExternalObjectsDropped” listener does get an e.subject collection that includes both the new Link and the new Node.

      "ExternalObjectsDropped": e => {
        e.subject.each(p => console.log(p.toString()));
      },

It also worked when first copying the collection to an Array, as your code does.

I drag the node from different diagram, during the drag I can see the node with the link, (the same as in the picture above)

I also tried e.subject.each, but it only showed the link, not the Node

Here’s my test sample:

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Editor</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
  <div style="width: 100%; display: flex; justify-content: space-between">
    <div style="display: flex; flex-direction: column; margin: 0 2px 0 0">
      <div id="myPaletteDiv" style="flex-grow: 1; width: 100px; background-color: floralwhite; border: solid 1px black"></div>
      <div id="myOverviewDiv" style="margin: 2px 0 0 0; width: 100px; height: 100px; background-color: whitesmoke; border: solid 1px black"></div>
    </div>
    <div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
  </div>
  <div>
    <button id="myLoadButton">Load</button>
    <button id="mySaveButton">Save</button>
  </div>
  <textarea id="mySavedModel" style="width:100%;height:200px">
{ "class": "go.GraphLinksModel",
  "nodeDataArray": [
{"key":1, "text":"hello", "color":"green", "location":"0 0"},
{"key":2, "text":"world", "color":"red", "location":"70 0"}
  ],
  "linkDataArray": [
{"from":1, "to":2}
  ]}
  </textarea>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

// initialize main Diagram
const myDiagram =
  new go.Diagram("myDiagramDiv",
    {
      "ExternalObjectsDropped": e => {
        e.subject.toArray().forEach(p => console.log(p.key, p.toString()));
      },
      "undoManager.isEnabled": true
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    { locationSpot: go.Spot.Center },
    new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
    $(go.Shape,
      {
        fill: "white", stroke: "gray", strokeWidth: 2,
        portId: "", fromLinkable: true, toLinkable: true,
        fromLinkableDuplicates: true, toLinkableDuplicates: true,
        fromLinkableSelfNode: true, toLinkableSelfNode: true
      },
      new go.Binding("stroke", "color")),
    $(go.TextBlock,
      {
        margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
        minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN),
        editable: true
      },
      new go.Binding("text").makeTwoWay())
  );

// initialize Palette
myPalette =
  new go.Palette("myPaletteDiv",
    {
      nodeTemplateMap: myDiagram.nodeTemplateMap,
      model: new go.GraphLinksModel([
        { text: "red node", color: "red", key: 0 },
        { text: "green node", color: "green", key: 1 },
        { text: "blue node", color: "blue", key: 2 },
        { text: "orange node", color: "orange", key: 3 }
      ], [
        { from: 3, to: 3 }
      ])
    });

// initialize Overview
myOverview =
  new go.Overview("myOverviewDiv",
    {
      observed: myDiagram,
      contentAlignment: go.Spot.Center
    });

// save a model to and load a model from Json text, displayed below the Diagram
function save() {
  const str = myDiagram.model.toJson();
  document.getElementById("mySavedModel").value = str;
}
document.getElementById("mySaveButton").addEventListener("click", save);

function load() {
  const str = document.getElementById("mySavedModel").value;
  myDiagram.model = go.Model.fromJson(str);
}
document.getElementById("myLoadButton").addEventListener("click", load);

load();
  </script>
</body>
</html>

I can see that it works for you,
for me it doe not do that,
trying to think what is the differnce.

  • I drag from a different diagram (not a palleted)
  • the source diagram has different model the the target diagram

Oh, is the source diagram a GraphLInksModel and the target diagram a TreeModel, or vice versa? But that can’t be, since there’s no way to represent a graph with reflexive links in a TreeModel.

no both of them are GraphLinksModel.
In your sample i did change the pallet into a diagram and its still works.
I do not know what is the difference, it works for you but not for me

In my code I did remake some of the definitions and now it works,
I will try tomorrow to understand which one of them is causing the problem

if you add to the source

  myDiagram.maxSelectionCount=1 ;

then you will see the problem

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Editor</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
  <div style="width: 100%; display: flex; justify-content: space-between">
    <div style="display: flex; flex-direction: column; margin: 0 2px 0 0">
      <div id="myPaletteDiv" style="flex-grow: 1; width: 100px; background-color: floralwhite; border: solid 1px black"></div>
      <div id="myOverviewDiv" style="margin: 2px 0 0 0; width: 100px; height: 100px; background-color: whitesmoke; border: solid 1px black"></div>
    </div>
    <div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
  </div>
  <div>
    <button id="myLoadButton">Load</button>
    <button id="mySaveButton">Save</button>
  </div>
  <textarea id="mySavedModel" style="width:100%;height:200px">
{ "class": "go.GraphLinksModel",
  "nodeDataArray": [
{"key":1, "text":"hello", "color":"green", "location":"0 0"},
{"key":2, "text":"world", "color":"red", "location":"70 0"}
  ],
  "linkDataArray": [
{"from":1, "to":2}
  ]}
  </textarea>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

// initialize main Diagram
const myDiagram =
  new go.Diagram("myDiagramDiv",
    {
      maxSelectionCount:1,
      "ExternalObjectsDropped": e => {
        e.subject.toArray().forEach(p => console.log(p.key, p.toString()));
      },
      "undoManager.isEnabled": true
    });

  
myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    { locationSpot: go.Spot.Center },
    new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify),
    $(go.Shape,
      {
        fill: "white", stroke: "gray", strokeWidth: 2,
        portId: "", fromLinkable: true, toLinkable: true,
        fromLinkableDuplicates: true, toLinkableDuplicates: true,
        fromLinkableSelfNode: true, toLinkableSelfNode: true
      },
      new go.Binding("stroke", "color")),
    $(go.TextBlock,
      {
        margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
        minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN),
        editable: true
      },
      new go.Binding("text").makeTwoWay())
  );

// initialize Palette
myPalette =
  new go.Palette("myPaletteDiv",
    {
      nodeTemplateMap: myDiagram.nodeTemplateMap,
      model: new go.GraphLinksModel([
        { text: "red node", color: "red", key: 0 },
        { text: "green node", color: "green", key: 1 },
        { text: "blue node", color: "blue", key: 2 },
        { text: "orange node", color: "orange", key: 3 }
      ], [
        { from: 3, to: 3 }
      ])
    });

// initialize Overview
myOverview =
  new go.Overview("myOverviewDiv",
    {
      observed: myDiagram,
      contentAlignment: go.Spot.Center
    });

// save a model to and load a model from Json text, displayed below the Diagram
function save() {
  const str = myDiagram.model.toJson();
  document.getElementById("mySavedModel").value = str;
}
document.getElementById("mySaveButton").addEventListener("click", save);

function load() {
  const str = document.getElementById("mySavedModel").value;
  myDiagram.model = go.Model.fromJson(str);
}
document.getElementById("myLoadButton").addEventListener("click", load);

load();
  </script>
</body>
</html>

Hmmm, yes, there’s a distinction between Diagram.selection and the collection of Parts that are actually moved/copied/deleted. We’ll look into this.

[EDIT] I just tried your code, completely unmodified, and drag-and-dropping the node with the reflexive link worked as I would have expected:

image

try this

just to remind you the problem is that I do not get the NODE on the ExternalObjectsDropped event

Oh, so the problem isn’t that the drop doesn’t copy both the node and its link, but that because you have limited how many can be selected, the Diagram.selection might not include the node. Well, if what is selected is a link, you could look at its Link.toNode.

this is basically what I did in my workaround, but it looks strange code.

I t is strange because I drag a Node and the Drop is a Link

By chance the Link was selected first, and the Diagram.maxSelectionCount prevented the Node from being selected. But we’ll consider fixing it so that the DiagramEvent.subject is not the Diagram.selection but is a separate collection. It will be in the next release, which shouldn’t be too long now – next week?