Relinking Provides wrong Arguments in LinkConnected Callback

Hello,

we have stumbled upon an issue with relinking links between different nodes.

As example. we have 2 nodes with 3 output ports each. Those ports have the same portIds. “1”, “2” and “3”.
Example nodes:
[
{id: 1, label: A, ports: [{label: “A1”, id: “1”},{label: “A2”, id: “2”},{label: “A3”, id: “3”}]},
{id: 2, label: B, ports: [{label: “B1”, id: “1”},{label: “B2”, id: “2”},{label: “B3”, id: “3”}]}
]

The ports are represented in the diagram in their respective template as textBlocks. In the template, we assign a custom function to the linkConnected callback. This function has 3 arguments, which should be:

thisNode: the new node the link got connected to.
newLink: the new link that got connected.
thisPort: the port that got connected to.

When relinking a link from node1 port1 to node1 port2, this callback does not get executed at all. Which is quite cumbersome because we now have to manually listen to the diagram LinkRelinked event and execute our similar code there. Why is there no LinkRelinked callback on the node or something similar?
When relinking a link from node1 port1 to node2 port3, the newLink and thisPortarguments inside the callback are wrong.
While debugging this issue, we found what we assume is the cause of this behaviour.

reconnectLink executes and sets t(the link) fromNode which then causes the setter to execute our callback LinkConnectedbefore fromPort or its portId was changed. Resulting in a wrong link and port.

So instead of getting node2 port3, you get node2 port1, because the portId of the old port is matched on the newNode, instead of the port with the new portId.
We assume this is a problem (bug) with the program execution timeline.

Yes, the Node.linkConnected and Node.linkDisconnected event handlers just handle when the link changes nodes. I can see how it might be helpful if it handled port changes for the same node.

Those two event handlers are called even if the reconnection isn’t done interactively via the LinkRelinkingTool, whereas the “LinkRelinked” DiagramEvent is only raised when that tool succeeds. Not due to programmatic modifications of a Link.

Yes, when the LinkRelinkingTool.reconnectLink method reconnects a Link, it first sets the node and then the portId. Which is why the Node’s event handlers are run first, followed by the RelinkingTool’s DiagramEvent after all has finished. So you are correct that temporarily the link is connecting with the same named port on the new node, if it exists. That’s just a result from modifying two properties in the same operation – temporarily only one of the two properties is set before the other one is set. If we had set the two properties in the opposite order, one would temporarily have a similar but different “wrong” configuration of the link.

There is a lot of other state that is temporarily wrong as changes are made. For example, when a link is made to connect between two nodes, temporarily the link is only connected to one of the nodes, and then the other end is connected. That is why the documentation for the Node.linkConnected event says:

However, the other end of the link may not yet have been connected with a node (and might never be), so you cannot depend on looking at what the link connects with.

Or, for example, considering moving a node. Until the links connected with that node are re-routed, their routes will not be correct. Unlike the above two cases of inconsistency, the time between when a node is moved and links being re-routed might be a long time. Only the end of a transaction will try to make sure everything is consistent.