Moveable/Draggable ports

I am assuming that you are using extensions/PortShiftingTool, as you indicated above.

Is the Panel with the Binding of “itemArray” also a “Spot” Panel?

Do you have a Binding of “portId” on the Panel.itemTemplate, and do you make sure each portId has a unique value within the node?

These requirements are determined by the PortShiftingTool.findPort method.

The itemArray are binded on the main Panel, the Node.
Yes, i bind the portId on the Panel.itemtemplate and the portId is unique : “-9”.
i noticed that the canStart() method on PortShiftingTool.js returns false for the
question :
if (!this.isBeyondDragSize()) and as result, does not continue to this.findPort()

here is my node template definition.

Until the user actually moves the mouse/finger enough, the PortShiftingTool won’t run.

It’s suspicious that you set the Shape.alignment, when you really want to set the Panel.alignment – that is you want to set the alignment of the port, not of the Shape within the Panel.

when i use the following template, it works fine (the portId is hard coded into the shape) :
diagram.nodeTemplate =
$(go.Node, “Spot”, nodeStyle(),
$(go.Picture, { width: 100, height: 100 }, new go.Binding(“source”) ),
$(go.Shape, “Rectangle”, portStyle(false), { portId: “dd” })
);

But when i use the following template with itemArray, i cannot move the port:

diagram.nodeTemplate =
$(go.Node, “Spot”, nodeStyle(),
new go.Binding(“itemArray”, “items”),
$(go.Picture, { width: 100, height: 100 }, new go.Binding(“source”) ),

        {
            itemTemplate : $(go.Panel,
                new go.Binding("portId", "id"),
                new go.Binding("alignment", "spot", go.Spot.parse),
                $(go.Shape, "Rectangle", portStyle(false))
            )
        }
    );

var nodeDataArray = [
{ key: nodeKey++, source: “icons/Router.svg”, siteId: “100/TS-XDM1000-KSDH-A-01”, loc: “0 500”, items: [ { id:“H01Rx”, spot: “0.5 0.5 0.5 0.5” } ] },
];

Where do i go wrong ?

You probably have done nothing wrong – there’s a bug in PortShiftingTool.findPort, since it does not handle nested panels correctly. You can modify extensions/PortShiftingTool.js as follows:

PortShiftingTool.prototype.findPort = function() {
  var diagram = this.diagram;
  var e = diagram.firstInput;
  var elt = diagram.findObjectAt(e.documentPoint, null, null);

  if (elt === null || !(elt.part instanceof go.Node)) return null;
  while (elt !== null && elt.panel !== null) {
    if (elt.panel.type === go.Panel.Spot && elt.panel.findMainElement() !== elt &&
        elt.portId !== null && elt.portId !== "") return elt;
    elt = elt.panel;
  }
  return null;
};

I applied the changes and it works perfect.
Thanks

Walter,
The bug fix does support nested panels, yet, when i move the ports and then move the whole node, the ports return to their original location.
If i use the simple template without nested panels, the port remain at its last location.

I played around with my node template and commented out the alignment binding inside the itemTemplate.
Once i commentated out, the ports retain at their last location.
So, I cannot use the alignment binding ?
See the node Template :
diagram.nodeTemplate =
$(go.Node, “Spot”, nodeStyle(),
$(go.Picture, { width: 100, height: 100 }, new go.Binding(“source”) ),
new go.Binding(“itemArray”, “items”),
{
itemTemplate : $(go.Panel, “Vertical”,
new go.Binding(“portId”, “id”),
// new go.Binding(“alignment”, “spot”, go.Spot.parse),
$(go.Shape, “Rectangle”, portStyle(false)),
$(go.TextBlock, { margin: 4 }, new go.Binding(“text”, “id”))
)
}
);

Note that the PortShiftingTool sets the alignment property. You need to make the Binding a TwoWay Binding so that it remembers the new alignment. Otherwise whenever the Binding is evaluated it will use the original alignment.

I bet that without any other actions, if you save the model and then reload it, you will see that the model still contains the original alignment. Until you change the Binding to remember the new alignment in the model data.

Yes, i did try the
new go.Binding(“alignment”, “spot”, go.Spot.parse).makeTwoWay(go.Spot.stringify),
And it works find.
Thanks

I wonder why cant i draw links between the ports.
I set all necessary params, but when i press the port, i drag the whole node.

It looks that i put the fromLinkable/toLinkable on the wrong place.
Fixed.
Thanks

Now a link can be created between ports, but after it is created, it is drawn between the nodes
Any idea ?

Read:
http://gojs.net/latest/intro/ports.html#GeneralPorts
and in particular note:

I applied all the rules.
Here is the a sample of the data and the templates :

var nodeDataArray = [ // a JavaScript Array of JavaScript objects, one per node;
// the “color” property is added specifically for this app
{ key: nodeKey++, source: “icons/Router.svg”, siteId: “100/TS-XDM1000-KSDH-A-01”, ipAddress: “1.10.11.23”, loc: “0 500”, ports: [ { id:“H01Rx”, spot: “1 0.5 0 0” }, { id:“H02Rx”, spot: “0 0.6 0 0”} ] },
{ key: nodeKey++, source: “icons/Router.svg”, siteId: “200”, loc: “200 500” , ports: [ { portColor:"#d488a2", id:“top1”, spot: “0 0.5 0 0” } ] }
];
var linkDataArray =
[ // a JavaScript Array of JavaScript objects, one per link
{ from: “1”, to: “2”, fromPort : “H01Rx”, toPort: “top1” },
// { from: “4”, to: “3” },
// { from: “4”, to: “2” }
];

diagram.model.linkFromPortIdProperty = “fromPort”;
diagram.model.linkToPortIdProperty = “toPort”;
diagram.model.linkFromKeyProperty = “from”;
diagram.model.linkToKeyProperty = “to”;

diagram.nodeTemplate =
$(go.Node, “Vertical”, nodeStyle(),
$(go.TextBlock, { margin: 4 }, new go.Binding(“text”, “siteId”)),
$(go.Panel, “Spot”,
$(go.Panel, “Spot”,
$(go.Shape, “Rectangle”, { width: 130, height: 130, fill: “white”, isPanelMain: true } ),
$(go.Picture, { width: 100, height: 100 }, new go.Binding(“source”) )
),
new go.Binding(“itemArray”, “ports”),
{
itemTemplate : $(go.Panel, “Vertical”,
new go.Binding(“portId”, “id”),
new go.Binding(“alignment”, “spot”, go.Spot.parse).makeTwoWay(go.Spot.stringify),
{ fromLinkable: true, toLinkable: true, toMaxLinks: 1, toSpot: go.Spot.Top, fromSpot: go.Spot.Top },
$(go.Shape, “Rectangle”, { desiredSize: new go.Size(6, 6), fill: “black”, cursor: “pointer”, }), // portStyle(false)),
$(go.TextBlock, { margin: 4 }, new go.Binding(“text”, “id”))
)
}
),
$(go.TextBlock, { margin: 4 }, new go.Binding(“text”, “ipAddress”))
);

What do i miss ?

You didn’t say how you got the node data and the link data into the model.

I’m not sure i understand.
I used the binding…is this what you’re asking ?

diagram.model = new go.GraphLinksModel(nodeDataArray,linkDataArray);

found the problem,
i set

diagram.model.linkFromPortIdProperty = “fromPort”;
diagram.model.linkToPortIdProperty = “toPort”;
diagram.model.linkFromKeyProperty = “from”;
diagram.model.linkToKeyProperty = “to”;

BEFORE

diagram.model = new go.GraphLinksModel(nodeDataArray,linkDataArray);

When i switched the order it works
Thanks