I want to get the shortest port distance between two node for every node we have two ports

I have two nodes each have two ports
So when I will drop the node is there any find closest port and connect automatically in GoJs.

Any help would appreciate just want to in gojs we can achieve or not. I didn’t find any example with ports.

You can iterate over the ports to find each one’s center point in document coordinates:

aNode.ports.each(function(port) {
    var p = port.getDocumentPoint(go.Spot.Center);
    . . .

Hi ,
getting error part.ports is not a function.

nearby.each(function (part) {

            let distance = part.location.distanceSquaredPoint(droppt)


                var p = port.getDocumentPoint(go.Spot.Center);


            //part.actualBounds.center.distanceSquaredPoint(droppt) < dist

            let isNodePart = part instanceof go.Node;

            if (distance && isNodePart && part.data.key != dropedNodeKey) {

                dist = part.actualBounds.center.distanceSquaredPoint(droppt);

                closest = part;



Make sure part instanceof go.Node.

Hi walter,
yes it is part of node.
Is there any way find the closest node after drag node from the palette
I am using below one
dist = part.actualBounds.center.distanceSquaredPoint(droppt);
but using this I am not getting correct point .

Node.ports is a property that returns a collection – it is not a function.

part.ports.each(port => ...);

ok Walter
droppt-- this my dragged node location
and part.location.x and y I have other node location which present in the canvas.
and I am using below two method finding the closest node and when I am dragged the node one after one so, I am getting first node location closest compare to other node which is closest

  1. var d=droppt.distanceSquared(part.location.x,part.location.y);
    var d1=part.actualBounds.center.distanceSquaredPoint(droppt);
    but not getting accepted result .


Here you go: https://gojs.net/extras/htmlDragDrop2.html
Each node has two ports, an input and an output.
Dropping a new node from the HTML panel will try to make up to two new links to the new node from an existing node with an unconnected output port and to an existing node with an unconnected input port.

Thanks walter
but I have few doubts here this is you node data structure

         var newdata = {
            location: point,
            text: event.dataTransfer.getData('text'),
            color: "lightyellow"
          var newnode = myDiagram.findNodeForData(newdata);

newnode- this is a node or part. the newnode you are taking directly from here but first I am adding the node in the model and then taking from nodedataarray and in that case I don’t have findPort function .
the attached screen this how I am getting node.

          var newinport = newnode.findPort("i");
          var newinpt = newinport.getDocumentPoint(go.Spot.Center);

but while I am doing
my node data structure

var newnode = this.diagram.model.nodeDataArray[index - 1]; // here I will get dropped node

Please format your code by surrounding it with lines consisting of triple backquote.
Did you have a question?

If you have a reference to a data object that you add to the model, you do not need to find it at the end of the Array.

actually I don’t have reference
while drop the node I will call another function which will create the node and add the node to model.
after that I will take the node the from nodeDataArray.

div1.addEventListener(“drop”, (event) => {
var newnode = this.myDiagram.model.nodeDataArray[1]// suppose this is the last node;
// after that when I will try
var newinport = newnode.findPort(“i”); // there is no findPort function.


my question can’t take the node from the nodeDataArray.

var newnode = myDiagram.findNodeForData(newdata); // is this line mandatory
instead of we can take dropped node from the nodeDataArray.

// whatever the example you have provided below
var newnode = myDiagram.findNodeForData(newdata); // instead of this line if I will write below
var i=myDiagram.model.nodeDataArray.length;
var newnode=myDiagram.model.nodeDataArray[i-1]; // here I will get last dropped node
but in this way I am not getting any function newnode.findPort(i) ; // giving error

Please keep the divide between model and diagram in mind.

  • Models have simple plain JavaScript data objects.
  • Diagrams have Nodes and Links.


So the data object that you add to the model will not have the properties or methods that the Node class has. That is why the code I gave you calls Diagram.findNodeForData. There are also other ways to find the Node in a Diagram for some model data object that is in a Model.

Thanks Walter I have done the changes somehow its working now but have problem in your example you are taking port left and right hand side. but in my example

in that what should be fromportid and toportid because I will find Port T and when I will drop connecting correctly. can you tell me in that case what should be fromportid and toportid because when I drop node top and bottom of the canvas it will differ closest port.

In my sample code, although there are two separate ports on each node, the port identifiers are hard-coded in the link template, so that information is not needed to be stored on the link data object.

If your nodes have different numbers of ports, or even just different port identifiers, you will need to generalize the code to find any ports to automatically connect with to handle the ports that are there and that you want to consider for connecting with. In my code I could assume that “i” was the identifier for the one input port, and that “o” was the identifier for the one output port. That simplified the code looking for nearby ports.

Hi walter,
why we are using isTopLevel and panel.
function (B) {

            while (B.portId !== pid && !B.isTopLevel) {

                B = B.panel;


A port element might be an arbitrarily complex panel. If one of its elements happens to be within X distance, we have to go up the parent GraphObject.panel chain to get to the port element – the one whose GraphObject.portId is not null and in this case is actually a particular string.

One should always write code that makes the fewest assumptions about anything it deals with. In this case there’s no reason to know how the node template is defined.

Hi Walter,
the example you have provider will it work with gojs palette also. or do you have any other example with gojs palette please let me know.

If you remove the code dealing with HTML drag-and-drop, and add the automatic linking code to an “ExternalObjectsDropped” DiagramEvent listener, yes that could work.

There are no other samples exactly like what you want, but this one is similar: https://gojs.net/extras/spliceNodeIntoLink.html
However in that sample the user needs to drop the Node onto a Link in order to splice it in.
Also, the nodes don’t have two ports.
But I hope you can learn from how the code is written.

Hi walter,
the html palette example you have given , you are getting node object using myDiagram.findNodeForData(newdata); but in “ExternalObjectsDropped” DiagramEvent listner , how I will get node object If I checking e.subject or other properties its not relevant.

var newdata = {
location: point,
text: event.dataTransfer.getData(‘text’),
color: “lightyellow”
var newnode = myDiagram.findNodeForData(newdata);

this.addDiagramListener(EventList.ExternalObjectsDropped, (e) => {
// here how I will mydiagram.findnodefordata();

In an “ExternalObjectsDropped” listener, the e.subject is the collection of selected Parts that have been created due to the drop. That’s how you find the newly dropped Node(s).