TreeModel not having any parent issue

Hi. I’m having a problem unlinking a node from its parent during drag and drop. I can set data.parent = undefined, but when I try to connect this node to any other parent again - it does not work.

How can I do that?

How are you setting that property? You should be calling https://gojs.net/latest/api/symbols/TreeModel.html#setParentKeyForNodeData

I’m doing this.diagram.model.setDataProperty(draggednode.data, 'parent', undefined);
Maybe that’s the issue I’ll replace it

It didn’t change anything. Issue is still present

Calling Model.set is fine if you haven’t set https://gojs.net/latest/api/symbols/TreeModel.html#nodeParentKeyProperty

To make everything clear.
I’ve overriden go.DraggingTool.doDragOver like this:

  1. I set the parent of the dragged node to undefined
  2. It creates temp node and a temp link linking it to the nearest node (Im deleting temp node and temp link in doDeactivate)

I’ve overriden go.DraggingTool.doDropOnto like this:

  1. If there is a node nearby - link them together
  2. If there is no node nearby - do nothing

The problem is that when I try to link this node again in doDropOnto the links appear invisible.

I can share my code, but it’s long and does many other stuff so I did this recap

What are you trying to accomplish? From your description, it sounds a bit like what this sample does: https://gojs.net/extras/autoLinkNearby.html

Yes something like that, except I’m using a TreeModel

What I’ve noticed is that after setting the node’s parent to undefined, suddenly any links with it are considered invalid. This happens in this function:

  public findNearestNode (pt: go.Point, draggednode: go.Node): any{
    var linkingTool = this.diagram.toolManager.linkingTool;
    var draggeds = this.draggedParts;
    var root = this.diagram.findNodeForKey(0);
    var near = this.diagram.findObjectsNear(pt, 150,
        // only consider undragged Nodes for which a new link would be valid
        function (x) {
            var p = x.part;
            if (draggeds && p instanceof go.Node &&
                !draggeds.contains(p) &&
                linkingTool.isValidLink(p, p.port, draggednode, draggednode.port)) {
                return p;
            }
            return root;
        });
    // find Node whose location is closest to PT
    var dist = Infinity;
    var nearest = null;
    near.each(function (n) {
        var d2 = n.location.distanceSquaredPoint(pt);
        if (d2 < dist) {
            dist = d2;
            nearest = n;
        }
    });
    return nearest;
  };

Here is a complete sample. I find that after clicking the “Test” button, which sets data.parent to undefined for the “Gamma” node, the link is removed between “Alpha” and “Gamma”, as expected. Furthermore the user can draw a new link from “Alpha” to “Gamma”.

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2021 by Northwoods Software Corporation. -->
  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
        {
          layout: $(go.TreeLayout),
          "undoManager.isEnabled": true,
          "ModelChanged": function(e) {     // just for demonstration purposes,
            if (e.isTransactionFinished) {  // show the model data in the page's TextArea
              document.getElementById("mySavedModel").textContent = e.model.toJson();
            }
          }
        });

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

    myDiagram.model = new go.TreeModel(
    [
      { key: 1, text: "Alpha", color: "lightblue" },
      { key: 2, text: "Beta", color: "orange", parent: 1 },
      { key: 3, text: "Gamma", color: "lightgreen", parent: 1 },
      { key: 4, text: "Delta", color: "pink", parent: 3 }
    ]);
  }

  function test() {
    myDiagram.model.commit(m => {
      m.set(m.nodeDataArray[2], "parent", undefined);
    });
  }
  </script>
</head>
<body onload="init()">
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  <button onclick="test()">Test</button>
  <textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
</body>
</html>