Hi, I noticed an issue with the AlignAll
option introduced in GoJS 2.3.
As you could see in the screen recording below, adding a node causes a link over a node even I set routing: go.Link.AvoidsNodes
in the linkTemplate.
If I comment out the AlignAll
option in groupTemplate, there is no link routing issue, as shown in the screen recording below.
If I reload the browser with the updated nodeDataArray
and linkDataArray
, there is no routing issue either with alignOption: go.LayeredDigraphLayout.AlignAll
, as shown below.
So, the routing issue only happens when a node is dynamically added to the diagram. Is there a way to solve this issue? I am posting the HTML + JS code below. You can copy it into an html file, open it in a browser, and click the Add Box button to check the issue.
Thanks!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
#file-upload {
display: none;
}
</style>
<title>Document</title>
</head>
<body>
<div
id="myDiagramDiv"
style="border: solid 1px black; width: 100%; height: 700px"
></div>
<div class="row">
<button id="add">Add Box</button>
</div>
<script src="../../site/release/go-debug.js"></script>
<script>
function init() {
const $ = go.GraphObject.make;
myDiagram = $(go.Diagram, "myDiagramDiv", {
layout: $(go.LayeredDigraphLayout, {
layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
packOption: go.LayeredDigraphLayout.PackStraighten,
aggressiveOption: go.LayeredDigraphLayout.AggressiveNone,
layerSpacing: 50,
linkSpacing: 20,
alignOption: go.LayeredDigraphLayout.AlignAll,
}),
});
myDiagram.nodeTemplateMap.add("global", $(
go.Node,
"Spot",
$(go.Shape, "Circle", {
fill: "transparent",
stroke: '#01778e',
width: 50,
height: 50,
portId: "",
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
}),
$(
go.TextBlock,
new go.Binding("text", "key"),
{
verticalAlignment: go.Spot.Center,
textAlign: "center",
stroke: '#1d2024',
},
),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(0, 0.5, 0, 0),
portId: "Left",
fromSpot: go.Spot.Left,
toSpot: go.Spot.Left,
}),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(1, 0.5, 0, 0),
portId: "Right",
fromSpot: go.Spot.Right,
toSpot: go.Spot.Right,
}),
));
myDiagram.nodeTemplateMap.add("", $(
go.Node,
"Spot",
$(go.Shape, "Rectangle", {
fill: "transparent",
stroke: "transparent",
width: 124,
height: 152,
portId: "",
fromLinkable: true,
toLinkable: true,
cursor: "pointer",
}),
$(
go.Panel,
"Position",
$(go.Shape, "RoundedRectangle", {
fill: "transparent",
width: 64,
height: 64,
position: new go.Point(0, 12),
}),
$(
go.TextBlock,
new go.Binding("text", "key"),
{
width: 64,
position: new go.Point(0, 84),
verticalAlignment: go.Spot.Center,
textAlign: "center",
},
),
),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(0, 0.5, 30, 0),
portId: "Left",
fromSpot: go.Spot.Left,
toSpot: go.Spot.Left,
}),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(1, 0.5, -30, 0),
portId: "Right",
fromSpot: go.Spot.Right,
toSpot: go.Spot.Right,
}),
));
myDiagram.nodeTemplateMap.add("group-end", $(go.Node, 'Spot',
$(go.Shape, "Circle", {
width: 0,
height: 0,
alignment: go.Spot.Center,
fill: null,
stroke: null,
}),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(0, 0.5),
portId: "Left",
fromSpot: go.Spot.Left,
toSpot: go.Spot.Left,
}),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(1, 0.5),
portId: "Right",
fromSpot: go.Spot.Right,
toSpot: go.Spot.Right,
}),
));
myDiagram.linkTemplate = $(
go.Link,
go.Link.Orthogonal,
{
relinkableFrom: true,
relinkableTo: true,
selectable: true,
reshapable: true,
corner: 10,
toShortLength: 8,
fromEndSegmentLength: 40,
toEndSegmentLength: 40,
routing: go.Link.AvoidsNodes,
},
$(go.Shape, { isPanelMain: true, strokeWidth: 1 }),
$(go.Shape, {
toArrow: "Standard",
}),
);
myDiagram.groupTemplate = $(
go.Group,
"Spot",
{
layout: $(go.LayeredDigraphLayout, {
layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
packOption: go.LayeredDigraphLayout.PackStraighten,
aggressiveOption: go.LayeredDigraphLayout.AggressiveNone,
layerSpacing: 50,
linkSpacing: 20,
alignOption: go.LayeredDigraphLayout.AlignAll,
}),
},
$(go.Panel, "Horizontal",
$(go.Shape, "Rectangle", {
width: 30,
fill: "transparent",
strokeWidth: 0,
stretch: go.GraphObject.Fill
}),
$(go.Panel, "Auto",
$(go.Shape, "Rectangle", {
fill: "transparent",
strokeWidth: 0,
stretch: go.GraphObject.Fill
}),
$(go.Panel, "Auto",
$(
go.Shape,
"RoundedRectangle", // surrounds everything
{
parameter1: 10,
fill: "white",
stroke: '#999999',
minSize: new go.Size(240, 220),
spot1: go.Spot.TopLeft,
spot2:go.Spot.BottomRight
}
),
$(
go.Panel,
"Vertical", // position header above the subgraph
$(go.Panel, "Auto", {
height: 28,
alignment: go.Spot.Left,
padding: new go.Margin(8, 12, 0, 12),
}, $(go.TextBlock, // stage title near top, next to button
new go.Binding("text", "key")
)),
$(
go.Placeholder, // represents area for all member parts
{
padding: new go.Margin(4, 0, 4, 0),
background: "transparent",
minSize: new go.Size(240, 160),
}
),
$(go.Panel, "Auto", {
height: 28,
stretch: go.GraphObject.Fill
})
)
)
),
$(go.Shape, "Rectangle", {
width: 30,
fill: "transparent",
strokeWidth: 0,
stretch: go.GraphObject.Fill
})
),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(0, 0.5, 30, 0),
portId: "Left",
fromSpot: go.Spot.Left,
toSpot: go.Spot.Left,
}),
$(go.Shape, "Rectangle", {
fill: null,
stroke: null,
desiredSize: new go.Size(0, 0),
alignment: new go.Spot(1, 0.5, -30, 0),
portId: "Right",
fromSpot: go.Spot.Right,
toSpot: go.Spot.Right,
}
));
const nodeDataArray = [
{
key: "Start",
category: "global",
},
{
key: "End",
category: "global",
},
{
key: "Group1",
isGroup: true,
},
{
key: "Group1-start",
group: "Group1",
category: "group-end"
},
{
key: "Group1-end",
group: "Group1",
category: "group-end"
},
{
key: "Box1",
group: "Group1",
},
{
key: "Box2",
group: "Group1",
},
{
key: "Box3",
group: "Group1",
},
{
key: "Box4",
group: "Group1",
}
];
const linkDataArray = [
{
from: "Start",
to: "Group1",
fromPort: "Right",
toPort: "Left",
},
{
from: "Group1",
to: "End",
fromPort: "Right",
toPort: "Left",
},
{
from: "Group1-start",
to: "Box1",
fromPort: "Right",
toPort: "Left",
},
{
from: "Box1",
to: "Box2",
fromPort: "Right",
toPort: "Left",
},
{
from: "Box2",
to: "Box3",
fromPort: "Right",
toPort: "Left",
},
{
from: "Box2",
to: "Box4",
fromPort: "Right",
toPort: "Left",
},
{
from: "Box3",
to: "Group1-end",
fromPort: "Right",
toPort: "Left",
},
{
from: "Box4",
to: "Group1-end",
fromPort: "Right",
toPort: "Left",
}
];
const model = new go.GraphLinksModel();
model.nodeDataArray = nodeDataArray;
model.linkDataArray = linkDataArray;
model.linkFromPortIdProperty = "fromPort";
model.linkToPortIdProperty = "toPort";
model.nodeGroupKey = "group";
myDiagram.model = model;
}
window.addEventListener("DOMContentLoaded", init);
document.getElementById('add').addEventListener('click', e => {
const groupKey = 'Group1'
const endKey = `${groupKey}-end`;
const existingKey = 'Box1';
const newKey = `Box5`;
myDiagram.model.addNodeData({ key: newKey, group: groupKey });
myDiagram.model.addLinkData({
from: existingKey,
fromPort: "Right",
to: newKey,
toPort: "Left",
});
myDiagram.model.addLinkData({
from: newKey,
fromPort: "Right",
to: endKey,
toPort: "Left",
});
});
</script>
</body>
</html>