Closed soonJ817 closed 2 months ago
First I should point out that executing a transaction within a loop, just as with any database application, is probably not a good idea. I'm concerned that there might be unexpected (to you) side-effects that happen towards the end of each transaction.
What are controlPointList
and controlPoint
, and what is the purpose of your code? Why are you calling findNodesByExample, which is an unreliable way to find some Nodes, unless you have been very careful, instead of Diagram.findNodeForKey? Why are you iterating over all of the Nodes reached from a Node and using that newValue
?
In this case, only one controlPoint value change event occurred. Afterwards, I found this case while tracking value changes. I did not expect that calling the findLinksOutOf function would change the result of findNodesOutOf as printed in the log.
Do you happen to know if the problem does not occur when using GoJS v2.3.17?
I'm unable to reproduce a bug. Perhaps I'm not testing exactly the situation that you have. Here's my code, as a complete stand-alone sample that highlights paths of nodes.
Two of the buttons start just with the "Omega" node; the other two buttons start with both nodes whose name starts with "O".
Two of the buttons highlight all of the nodes reachable from the starting node(s); the other two buttons only highlight those nodes whose name satisfies a predicate that checks for "e" in the name.
If you check the "Highlight Links" checkbox, it also highlights the links between the nodes. I think the code when not highlighting links is most like your code.
My code includes two console.log statements that are like yours. Commenting out one of them or both of them does not change the behavior.
So, how is my code meaningfully different from yours? How can I reproduce the problem?
<!DOCTYPE html>
<html>
<head>
<title>Highlighting paths</title>
<!-- Copyright 1998-2024 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:200px"></div>
<button id="myTestButton3">Root is "Omega" (no predicate)</button>
<button id="myTestButton4">Root is "Omega", "e" predicate</button>
<button id="myTestButton">Start with "O" (no predicate)</button>
<button id="myTestButton2">Start with "O", "e" predicate</button>
<input type=checkbox id="myHighlightLinks"></input>
<label for="myHighlightLinks">Highlight Links</label>
<textarea id="myOutput" style="width:100%;height:300px"></textarea>
<script src="https://unpkg.com/gojs@3.0"></script>
<script id="code">
const myDiagram =
new go.Diagram("myDiagramDiv", {
layout: new go.LayeredDigraphLayout(),
"undoManager.isEnabled": true
});
myDiagram.nodeTemplate =
new go.Node()
.bindObject("background", "isHighlighted", h => h ? "lime" : null)
.add(
new go.TextBlock()
.bind("text", "name")
);
myDiagram.linkTemplate =
new go.Link()
.add(
new go.Shape({ strokeWidth: 1.5 })
.bindObject("stroke", "isHighlighted", h => h ? "lime" : "black"),
new go.Shape({ toArrow: "Standard", strokeWidth: 0 })
.bindObject("fill", "isHighlighted", h => h ? "lime" : "black")
);
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, name: "Omicron" },
{ key: 2, name: "Rho" },
{ key: 3, name: "Omega" },
{ key: 4, name: "Delta" },
{ key: 5, name: "Zeta" },
{ key: 6, name: "Phi" },
{ key: 7, name: "Chi" },
],
[
{ from: 1, to: 2 },
{ from: 1, to: 4 },
{ from: 1, to: 7 },
{ from: 3, to: 2 },
{ from: 3, to: 4 },
{ from: 3, to: 7 },
{ from: 2, to: 5 },
{ from: 2, to: 6 },
{ from: 4, to: 5 },
{ from: 4, to: 6 },
]);
function follow(node, pred, indent, msg) {
if (indent === undefined) indent = 0;
if (msg === undefined) msg = "";
node.isHighlighted = true;
msg += "\n" + " ".repeat(indent) + node.data.name;
// Your code is like this:
console.log(node.data.name, node.findNodesOutOf().first()?.data.name, node.findLinksOutOf().first()?.data);
console.log(node.findNodesOutOf().first()?.data.name);
if (!document.getElementById("myHighlightLinks").checked) {
// Your code is like this:
node.findNodesOutOf().each(n => {
if (pred && !pred(n)) return;
msg = follow(n, pred, indent+1, msg);
});
} else {
// Alternatively, this also highlights links as well as nodes:
node.findLinksOutOf().each(l => {
const to = l.toNode;
if (pred && !pred(to)) return;
l.isHighlighted = true;
msg += "\n" + " ".repeat(indent+1) + l.toString();
msg = follow(to, pred, indent+2, msg);
});
}
return msg;
}
function highlightAndLog(startPattern, filterPredicate) {
myDiagram.commit(diag => {
diag.clearHighlighteds();
let msg = "";
diag.findNodesByExample({ name: startPattern }).each(root => {
msg += follow(root, filterPredicate);
});
document.getElementById("myOutput").textContent = msg;
});
}
document.getElementById("myTestButton").addEventListener("click", e => {
highlightAndLog(/O/);
});
document.getElementById("myTestButton2").addEventListener("click", e => {
highlightAndLog(/O/, n => n.data.name.indexOf("e") > 0); // predicate checks for "e" in data.name
});
document.getElementById("myTestButton3").addEventListener("click", e => {
highlightAndLog("Omega");
});
document.getElementById("myTestButton4").addEventListener("click", e => {
highlightAndLog("Omega", n => n.data.name.indexOf("e") > 0);
});
</script>
</body>
</html>
Thank you sincerely for your kindness. Lemme try.
Can you help me a little more? It's been less than a month since I started working with JavaScript and Vue code, so I'm not very good at it yet. I also couldn't reproduce it from the code you gave me. However, the same issue reappeared in v2.3.17.
Let me explain the behavior before that situation to understand more accurately. I initialized the diagram as follows:
const createDiagram = () =>
new go.Diagram(
diagramRef.value as HTMLDivElement,
{
"draggingTool.isGridSnapEnabled": true,
"draggingTool.gridSnapCellSize": go.Size.parse("5 5"),
initialContentAlignment: go.Spot.Center,
"undoManager.isEnabled": true,
} as DiagramInitOptions
);
...
const initLinkTemplate = () => {
const $ = go.GraphObject.make;
diagram.model = new go.GraphLinksModel({
linkFromPortIdProperty: "fromPort",
linkToPortIdProperty: "toPort",
});
diagram.linkTemplate = $(
go.Link,
{
routing: go.Routing.AvoidsNodes,
curve: go.Curve.JumpOver,
fromEndSegmentLength: 15,
toEndSegmentLength: 15,
corner: 3,
selectionAdorned: true,
},
$(go.Shape, { strokeWidth: 2, stroke: "red" }),
$(go.Shape, { toArrow: "OpenTriangle", stroke: "red" })
);
};
Then, data was injected as follows using the diagram.model.addLinkDataCollection
and diagram.model.addNodeDataCollection
functions.
{
"nodeDataArray": [
{
"key": "6a2312d5-eaee-45fb-bb71-3c8780729ebd",
"category": "관제점 4(Boolean)",
"objectType": "ControlPoint",
"loc": "-115 -280",
"value": false,
"name": "관제점 4(Boolean)"
},
{
"key": "ca1d4e2b-f833-4490-8de4-65547d214ecb",
"category": "관제점 5(Boolean)",
"objectType": "ControlPoint",
"loc": "-90 -175",
"value": false,
"name": "관제점 5(Boolean)"
},
{
"key": "b9be5628-36ce-4387-8614-c4303a224e84",
"category": "관제점 6(Boolean)",
"objectType": "ControlPoint",
"loc": "-120 -70",
"value": false,
"name": "관제점 6(Boolean)"
},
{
"key": "77285f99-bb68-4d9d-b1a4-679fb8666740",
"category": "관제점 7(Boolean)",
"objectType": "ControlPoint",
"loc": "-120 95",
"value": false,
"name": "관제점 7(Boolean)"
},
{
"key": "1b82094c-f2f4-4559-8f84-defad21d6c9e",
"category": "Counter",
"objectType": "Logic",
"loc": "120 -130",
"value": 10,
"name": "Counter"
},
{
"key": "71bf6ddf-c680-463a-8498-4708ab5ae0c1",
"category": "관제점 1",
"objectType": "ControlPoint",
"loc": "305 -135",
"value": 11,
"name": "관제점 1"
},
{
"key": "c8bddc73-7584-49b7-b5b8-53bdad5166a3",
"category": "LED",
"objectType": "Graphic",
"loc": "185 105",
"value": true,
"name": "LED",
"threshold": 10,
"controlPointName": "관제점 1"
}
],
"linkDataArray": [
{
"from": "6a2312d5-eaee-45fb-bb71-3c8780729ebd",
"to": "1b82094c-f2f4-4559-8f84-defad21d6c9e",
"fromPort": "out",
"toPort": "Count Up"
},
{
"from": "ca1d4e2b-f833-4490-8de4-65547d214ecb",
"to": "1b82094c-f2f4-4559-8f84-defad21d6c9e",
"fromPort": "out",
"toPort": "Count Down"
},
{
"from": "b9be5628-36ce-4387-8614-c4303a224e84",
"to": "1b82094c-f2f4-4559-8f84-defad21d6c9e",
"fromPort": "out",
"toPort": "Preset In"
},
{
"from": "77285f99-bb68-4d9d-b1a4-679fb8666740",
"to": "1b82094c-f2f4-4559-8f84-defad21d6c9e",
"fromPort": "out",
"toPort": "Clear In"
},
{
"from": "1b82094c-f2f4-4559-8f84-defad21d6c9e",
"to": "71bf6ddf-c680-463a-8498-4708ab5ae0c1",
"fromPort": "out",
"toPort": "in"
}
]
}
The following is an example of the Count Up
port panel definition. The definitions of all ports are in the same format.
new go.Panel('Table').add(
this.$(go.TextBlock, {background: 'white', text: "Count Up", width: 100, textAlign: 'center'}),
this.$(go.Shape, 'Rectangle', {
desiredSize: new go.Size(6, 6),
fill: 'black',
fromSpot: go.Spot.Right,
fromLinkable: isOut,
toSpot: go.Spot.Left,
toLinkable: !isOut,
cursor: 'pointer',
}, {portId: "Count Up", alignment: new go.Spot(+isOut, 0.5)}),
);
I think there's something wrong with using the port.
In the problematic part, when I print node.findNodesOutOf()
or node.findNodesConnected()
to the console, EmptyIterator
is output.
However, if you call a link-related function (findLinksConnected, etc.), the output is printed as expected, and the expected operation is performed from then on.
It could be that the node really doesn't have any nodes:
On Mon, Jul 15, 2024 at 9:36 PM soonJ817 @.***> wrote:
Can you help me a little more? It's been less than a month since I started working with JavaScript and Vue code, so I'm not very good at it yet. I also couldn't reproduce it from the code you gave me. However, the same issue reappeared in v2.3.17.
Let me explain the behavior before that situation to understand more accurately. I initialized the diagram as follows:
const createDiagram = () => new go.Diagram( diagramRef.value as HTMLDivElement, { "draggingTool.isGridSnapEnabled": true, "draggingTool.gridSnapCellSize": go.Size.parse("5 5"), initialContentAlignment: go.Spot.Center, "undoManager.isEnabled": true, } as DiagramInitOptions );
...
const initLinkTemplate = () => { const $ = go.GraphObject.make; diagram.model = new go.GraphLinksModel({ linkFromPortIdProperty: "fromPort", linkToPortIdProperty: "toPort", });
diagram.linkTemplate = $( go.Link, { routing: go.Routing.AvoidsNodes, curve: go.Curve.JumpOver, fromEndSegmentLength: 15, toEndSegmentLength: 15, corner: 3, selectionAdorned: true, }, $(go.Shape, { strokeWidth: 2, stroke: "red" }), $(go.Shape, { toArrow: "OpenTriangle", stroke: "red" }) ); };
Then, data was injected as follows using the diagram.model.addLinkDataCollection and diagram.model.addNodeDataCollection functions.
{ "nodeDataArray": [ { "key": "6a2312d5-eaee-45fb-bb71-3c8780729ebd", "category": "관제점 4(Boolean)", "objectType": "ControlPoint", "loc": "-115 -280", "value": false, "name": "관제점 4(Boolean)" }, { "key": "ca1d4e2b-f833-4490-8de4-65547d214ecb", "category": "관제점 5(Boolean)", "objectType": "ControlPoint", "loc": "-90 -175", "value": false, "name": "관제점 5(Boolean)" }, { "key": "b9be5628-36ce-4387-8614-c4303a224e84", "category": "관제점 6(Boolean)", "objectType": "ControlPoint", "loc": "-120 -70", "value": false, "name": "관제점 6(Boolean)" }, { "key": "77285f99-bb68-4d9d-b1a4-679fb8666740", "category": "관제점 7(Boolean)", "objectType": "ControlPoint", "loc": "-120 95", "value": false, "name": "관제점 7(Boolean)" }, { "key": "1b82094c-f2f4-4559-8f84-defad21d6c9e", "category": "Counter", "objectType": "Logic", "loc": "120 -130", "value": 10, "name": "Counter" }, { "key": "71bf6ddf-c680-463a-8498-4708ab5ae0c1", "category": "관제점 1", "objectType": "ControlPoint", "loc": "305 -135", "value": 11, "name": "관제점 1" }, { "key": "c8bddc73-7584-49b7-b5b8-53bdad5166a3", "category": "LED", "objectType": "Graphic", "loc": "185 105", "value": true, "name": "LED", "threshold": 10, "controlPointName": "관제점 1" } ], "linkDataArray": [ { "from": "6a2312d5-eaee-45fb-bb71-3c8780729ebd", "to": "1b82094c-f2f4-4559-8f84-defad21d6c9e", "fromPort": "out", "toPort": "Count Up" }, { "from": "ca1d4e2b-f833-4490-8de4-65547d214ecb", "to": "1b82094c-f2f4-4559-8f84-defad21d6c9e", "fromPort": "out", "toPort": "Count Down" }, { "from": "b9be5628-36ce-4387-8614-c4303a224e84", "to": "1b82094c-f2f4-4559-8f84-defad21d6c9e", "fromPort": "out", "toPort": "Preset In" }, { "from": "77285f99-bb68-4d9d-b1a4-679fb8666740", "to": "1b82094c-f2f4-4559-8f84-defad21d6c9e", "fromPort": "out", "toPort": "Clear In" }, { "from": "1b82094c-f2f4-4559-8f84-defad21d6c9e", "to": "71bf6ddf-c680-463a-8498-4708ab5ae0c1", "fromPort": "out", "toPort": "in" } ] }
The following is an example of the Count Up port panel definition. The definitions of all ports are in the same format.
new go.Panel('Table').add( this.$(go.TextBlock, {background: 'white', text: "Count Up", width: 100, textAlign: 'center'}), this.$(go.Shape, 'Rectangle', { desiredSize: new go.Size(6, 6), fill: 'black', fromSpot: go.Spot.Right, fromLinkable: isOut, toSpot: go.Spot.Left, toLinkable: !isOut, cursor: 'pointer', }, {portId: "Count Up", alignment: new go.Spot(+isOut, 0.5)}), );
I think there's something wrong with using the port. In the problematic part, when I print node.findNodesOutOf() or node.findNodesConnected() to the console, EmptyIterator is output. However, if you call a link-related function (findLinksConnected, etc.), the output is printed as expected, and the expected operation is performed from then on.
— Reply to this email directly, view it on GitHub https://github.com/NorthwoodsSoftware/GoJS/issues/219#issuecomment-2229817054, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACV7Y52GTLI2TEM3DRJCMG3ZMR2KBAVCNFSM6AAAAABKWQJV7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMRZHAYTOMBVGQ . You are receiving this because you commented.Message ID: @.***>
If there really are no nodes, then after calling findLinks, findNodes should also show no nodes. When I have time, I will create a stand-alone sample project. Thank you :-)
Hey, I think I found a bug. I'm using the latest version of GoJS with Vue 3. (
gojs": "^3.0.4
) I implemented it so that when the watched variable in Vue 3 is modified, the node's data is updated as follows.If I remove the two console logs in the
updateLinkedNodes
function, the "It doesn't enter here!" console doesn't get printed. When I run it with the two console logs, the firstnode.findNodesOutOf().first()?.data.name
comes out as undefined, but right after that, the name gets printed in the console below. If I removenode.findLinksOutOf().first()?.data
from the console, the second console also prints undefined. I have absolutely no idea why it behaves like this.