Changing stroke width on select - redrawing the graph

Hi,
There is a critical bug:
Let’s assume that the user changed the positions of some nodes (by dragging them) - any click on any node - redrawing the graph and resetting all of his work!! (of course that the bug also causes the process of changing the position to get disturbed because suddenly the graph can reset, etc).
I investigated it deeply, and the decisive conclusion was the code of changing the stroke width is causing all of this mess.

Why? Is there a way to change the stroke width other than simply:

selectionChanged(node) {
	const shape = node.findObject('ItemShape');
	if (node?.isSelected === true) {
	    shape.strokeWidth = 3;
        } else {
            shape.strokeWidth = 1;
	}
}

??
If not, can you please fix this bug as soon as possible?

Thanks,
Michael.

This is not a bug, but a consequence of a few rules:

  • By default, if you have set a layout, changing any Node’s size will invalidate that layout and cause a relayout.
  • StrokeWidth is part of a Shape’s size

You can fix it in a few different ways:

  1. Set the layout.isOngoing to false, and Node size changes won’t cause a relayout.
  2. Modify the node’s layoutConditions to remove LayoutNodeSized.
  3. Construct a Node template so that your selectionChanged is not really modifying the size, but merely
    appearing that it is.

If you don’t want to re-layout at all, the first one is the easiest. If you do want to re-layout on similar conditions, then you should do #3. You can do this by having two shapes that overlap, with different strokeWidth, and instead toggle their shape.opacity between 1 and 0. This ensures that no Shape (and therefore Node) remeasuring ever takes place on such changes. This is what the flowchart sample does for Link shapes, on hover.

Thanks for your answer.
I tried the isOngoing flag, but the layout is still invalidated.

Something else must be happening. What is your Diagram.layout? What happens if you also set Layout.isInitial to false? Do you have a TwoWay Binding on the Node.location property?

About Diagram.layout:

const buildDiagramInitSettings = () => ({
		allowCopy: false,
		allowGroup: false,
		allowInsert: false,
		allowLink: false,
		allowTextEdit: false,
		initialContentAlignment: go.Spot.Center,
		initialAutoScale: go.Diagram.Uniform,
		// scrollMode: go.Diagram.InfiniteScroll,

		layout: $(AlignedLayeredDigraphLayout, {
			columnSpacing: 15,
			layerSpacing: 100,
			linkSpacing: 150,
			layeringOption: go.LayeredDigraphLayout.LayerOptimalLinkLength,
			aggressiveOption: go.LayeredDigraphLayout.AggressiveMore,
			initializeOption: go.LayeredDigraphLayout.InitDepthFirstIn,
			packOption: go.LayeredDigraphLayout.PackStraighten,
			setsPortSpots: false,
			isRealtime: false,
                        isOngoing: false
		}),
	});

Unfortunately, isInitial: false not helping also.

What do you mean by “TwoWay Binding”?

Here’s a simple example demonstrating a layout that uses inOngoing: false to prevent relayouts. It’s not clear what else might be preventing your layout from functioning the same.

Regarding two-way bindings, they are bindings that update the data when the diagram change. Read about them here: GoJS Data Binding -- Northwoods Software

We decided to give up changing the stroke width.
Thank you anyway.