Change not within transaction on group Button?

Whenever I collapse the group via button, the following warning is printed:

`Change not within a transaction: !d points: Link#4233([object Object])  old: List(Point)#63064  new: List(Point)#64586`

I’m using the button provided by the samples - ‘SubGraphExpanderButton’.

Can you tell us how to reproduce the warning?

When I try collapsing and expanding groups in Grouping using the go-debug.js library, I do not get those warnings.

The error happens when I have nested groups. Let’s say that group A is level 0, and group B is inside A.
If group A contains a node connected to a port on group B, the warning displays when group B is being collapsed. Visually, I can see that group B, in my case, changes its position, hence the link needs to be resized. Perhaps that might be the source of the warning?

We’ll see if we can reproduce a problem.

Sorry, but I’ve tried a lot of combinations of situations and am still unable to reproduce the warning that you describe.

I’ve tried collapsing and expanding group containing nodes and links, with links connecting a member node to and from its containing group, links between groups and between member nodes in different groups, to particular and different ports, with and without AvoidsNodes routing, with and without Group.layout, after undo and redo, and probably some other stuff too.

What’s the smallest, simplest diagram in which you encounter the warning?

Oh, I assume everything is working well besides the warning, yes?

Are you making any changes while skipsUndoManager is true?

I am uploading a picture of the simplest case when this happens.

Yes, everything else is working great, I just wonder why I get this warning.
I’m not sure if I’m making any changes when skipsUndoManager is true. Can you tell me how I can check this?
I only set the following:

`'undoManager.isEnabled': true,`

Thanks. What do you do to produce the warning, and what does it look like afterwards?

Well, presumably you already searched for “skipsUndoManager”, so that’s the obvious case. The not-so-obvious cases are in event handlers where it’s documented that the handler is called while skipsUndoManager is temporarily set to true. For example: Part.selectionChanged.

To produce the warning, I simply collapse the inner group (group-2). It looks as expected. The subGraphParts are not visible, the group is collapsed

Do selectionGrouped or selectionDeleting have the same effect on skipsUndoManager? I’ve implemented my own onSelectionGrouped handler and onSelectionDeleting, but I don’t see why skipsUndoManager would still be set to true when I press the button.

I still can’t reproduce any warning. Here’s what I’m using:

    myDiagram.groupTemplate =
      $(go.Group, "Spot",
        { layout: $(go.TreeLayout) },
        $(go.Panel, "Auto",
          $(go.Shape, { fill: "white" }),
          $(go.Panel, "Table",
            $("SubGraphExpanderButton"),
            $(go.TextBlock, { column: 1 }, new go.Binding("text")),
            $(go.Placeholder, { row: 2, columnSpan: 2, padding: 10 })
          )
        ),
        $(go.Shape, "Circle", { alignment: go.Spot.Left, width: 4, height: 4, portId: "" })
      );

Which in my test case looks like:

The layout that I use is defined like this:

layout: $(go.LayeredDigraphLayout, {
                    isRealtime: false,
                    isOngoing: false,
                    layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
                    columnSpacing: 5,
                    layerSpacing: 5,
                    setsPortSpots: false
                })

This is the entire definition of the group:

$(go.Group, 'Spot',
        {
            isSubGraphExpanded: false,
            resizable: false,
            ungroupable: true,
            doubleClick: doubleClicked,
            locationObjectName: 'BODY',
            locationSpot: go.Spot.Center,
            selectionObjectName: 'BODY',
            resizeObjectName: 'BODY',
            computesBoundsAfterDrag: true,
            layout: $(go.LayeredDigraphLayout, {
                isRealtime: false,
                isOngoing: false,
                layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource,
                columnSpacing: 5,
                layerSpacing: 5,
                setsPortSpots: false
            })
        },
        new go.Binding('isSubGraphExpanded').makeTwoWay(),
        new go.Binding('resizable', 'isSubGraphExpanded', function (value, group) {

            let newHeight = Math.max(group.data.inputsArray.length, group.data.outputsArray.length) * 30;
            group.findObject('BODY').desiredSize = value ? new go.Size(NaN, NaN) : new go.Size(NaN, newHeight < 50 ? 50 : newHeight);

            return value;
        }),
        $(go.Panel, 'Auto',
            {
                name: 'BODY',
                stretch: go.GraphObject.Fill,
                minSize: new go.Size(100, 50)
            },
            $(go.Shape, group.shape, group.details,
                new go.Binding('opacity', 'isSubGraphExpanded', function (isExpanded, shape) {

                    return isExpanded ? 0.3 : 1;
                }).ofObject()),
            $(go.TextBlock, textBlock, { alignment: go.Spot.Center },
                new go.Binding('text', 'isSubGraphExpanded', function (isExpanded, textblock) {

                    return isExpanded ? '' : 'Not expanded';
                }).ofObject()),
            $(go.Panel, 'Table',
                {
                    minSize: new go.Size(100, NaN),
                    alignment: new go.Spot(0.5, 0, 0, -10),
                    alignmentFocus: go.Spot.Top
                },
                new go.Binding('desiredSize').makeTwoWay(),
                $(go.RowColumnDefinition, {row: 0, sizing: go.RowColumnDefinition.None}),
                {alignment: go.Spot.Top, stretch: go.GraphObject.Horizontal},
                $(go.RowColumnDefinition, {row: 1, sizing: go.RowColumnDefinition.None}),
                {alignment: go.Spot.Top, stretch: go.GraphObject.Horizontal},
                $(go.Shape, 'RoundedRectangle',
                    {
                        name: 'HEADER',
                        columnSpan: 3,
                        fill: 'transparent',
                        strokeWidth: 2,
                        stretch: go.GraphObject.Fill
                    },
                    new go.Binding('opacity', 'isSubGraphExpanded', function (isExpanded, shape) {

                        return isExpanded ? 0.15 : 0.5;
                    }).ofObject()),
                $('SubGraphExpanderButton', {column: 0, margin: new go.Margin(0, 0, 0, 2)}),
                $(go.TextBlock, {
                        textAlign: 'center',
                        column: 1,
                        columnSpan: 2,
                        editable: true
                    },
                    new go.Binding('text', 'name').makeTwoWay()),
                $(go.Placeholder,
                    {row: 1, columnSpan: 3, alignment: go.Spot.TopLeft},
                    new go.Binding('padding', 'isSubGraphExpanded', function (e) {
                        return e ? new go.Margin(5, 10) : new go.Margin(0);
                    }))
            )
        ),
        $(go.Panel, 'Vertical', {alignment: go.Spot.Left, padding: new go.Margin(15, 0, 0, 0)},
            new go.Binding('itemArray', 'inputsArray'),
            {
                itemTemplate: getItemTemplate(true)
            }
        ),
        $(go.Panel, 'Vertical', {alignment: go.Spot.Right, padding: new go.Margin(15, 0, 0, 0)},
            new go.Binding('itemArray', 'outputsArray'),
            {
                itemTemplate: getItemTemplate(false)
            }
        )

I can’t get that to work, even after commenting out stuff that you didn’t provide.

One thing I do notice – you really shouldn’t be modifying some other element (named “BODY”) in the conversion function from “isSubGraphExpanded” to “resizable”. And besides, what should be the source for that Binding? Not the data but .ofObject()?

Yeah, I wanted to resize the body of the group when it is collapsed and/or expanded to some value that I can calculate. I probably couldn’t think of any better way of doing it.
Perhaps that is the reason for the warning?

The BODY object does belong to the group whose isSubGraphExpanded has just changed.

Update on this… the warning stopped occuring when I removed:
curve: go.Link.JumpOver, from the link template. It looks like this now:

 $(go.Link, {

            selectable: true,
            // curve: go.Link.JumpOver,
            relinkableFrom: true,
            relinkableTo: true,
        },
        $(go.Shape, {strokeWidth: 2}),
        $(go.Shape, {toArrow: 'standard'}));

Try setting Group | GoJS API to false. I’m guessing that having JumpOver curve Links is causing some Groups to change in size. That means that some Groups are changing size just because of how some links are crossing over each other, which would seem to be a “random” phenomenon.

If that avoids the warnings for you, we’ll need to investigate what we can do about that.

In the meantime, the warnings should be harmless – any ChangedEvents that happen outside of a transaction automatically get included in the next transaction.

OK, I just tested this, and my guess was wrong – that wasn’t the problem, and I’m still unable to reproduce the warning messages.

But I am curious whether using curve: go.Link.JumpGap also causes you to get those out-of-transaction warnings.

I was talking only about the out of transaction warnings.

Yes, that’s the subject of this forum topic.