First, an unrelated suggestion. Three of your Bindings are like:
new go.Binding('stroke', '', ({ data }) => LINK_COLORS[data.state]).ofObject(),
I believe this could more clearly be written:
new go.Binding('stroke', 'state', state => LINK_COLORS[state]),
Second, I used your link template in a copy of the Minimal sample and did not encounter any issues with undo/redo:
Here’s my complete test sample:
<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
<script src="https://unpkg.com/gojs"></script>
<script id="code">
const $ = go.GraphObject.make;
const myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"undoManager.isEnabled": true
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
$(go.Shape,
{ fill: "white" },
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 8 },
new go.Binding("text"))
);
const LINK_COLORS = ["black", "red", "green", "blue"];
myDiagram.linkTemplate =
go.GraphObject.make(
go.Link,
{
corner: 6,
selectionAdorned: false,
},
new go.Binding('curve', 'type', type => (type === 'revert' ? go.Link.Bezier : go.Link.JumpGap)),
new go.Binding('curviness', 'type', type => (type === 'revert' ? 100 : 0)),
new go.Binding('isShadowed', 'isSelected').ofObject(),
// the "line"
go.GraphObject.make(
go.Shape,
{ strokeWidth: 2, opacity: 1 },
//new go.Binding('stroke', '', ({ data }) => LINK_COLORS[data.state]).ofObject(),
new go.Binding('stroke', 'state', state => LINK_COLORS[state]),
new go.Binding('strokeDashArray', 'type', type => (type === 'revert' ? [6, 6] : [])),
new go.AnimationTrigger('stroke', { duration: 300 }),
),
{
//??? contextMenu: GraphObject.make(HTMLInfo, { show: () => {}, hide: hideContextMenu }),
},
// the "from" end arrowhead
go.GraphObject.make(
go.Shape,
{ fromArrow: 'Circle', stroke: null, scale: 1.2, strokeWidth: 2 },
new go.Binding('fill', '', ({ data, isSelected }) =>
isSelected ? '#FFFFFF' : LINK_COLORS[data.state],
).ofObject(),
new go.AnimationTrigger('fill', { duration: 300 }),
//new go.Binding('stroke', '', ({ data }) => LINK_COLORS[data.state]).ofObject(),
new go.Binding('stroke', 'state', state => LINK_COLORS[state]),
),
// the "to" end arrowhead
go.GraphObject.make(
go.Shape,
{ toArrow: 'RoundedTriangle', stroke: null, scale: 1.2, strokeWidth: 2 },
new go.Binding('fill', '', ({ data, isSelected }) =>
isSelected ? '#FFFFFF' : LINK_COLORS[data.state],
).ofObject(),
new go.AnimationTrigger('fill', { duration: 300 }),
//new go.Binding('stroke', '', ({ data }) => LINK_COLORS[data.state]).ofObject(),
new go.Binding('stroke', 'state', state => LINK_COLORS[state]),
),
{
shadowColor: 'grey',
shadowBlur: 12,
shadowOffset: new go.Point(0, 0),
mouseHover(e, node) {
node.isShadowed = true;
},
mouseLeave(e, node) {
if (!node.isSelected) node.isShadowed = false;
},
},
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, text: "Alpha", color: "lightblue" },
{ key: 2, text: "Beta", color: "orange" },
{ key: 3, text: "Gamma", color: "lightgreen" },
{ key: 4, text: "Delta", color: "pink" }
],
[
{ from: 1, to: 2, type: "revert" },
{ from: 1, to: 3, state: 2 },
{ from: 2, to: 2 },
{ from: 3, to: 4 },
{ from: 4, to: 1 }
]);
</script>
</body>
</html>
Note that I commented out the context menu, since I don’t know it and it probably is irrelevant to your issue.
So I suspect that there’s something else going on in your app to cause the problem.