How to Remove Specific Transactions from UndoManager in GoJS

Hello,

I am currently working on a project using GoJS version 2.3.12 along with gojs-react version 1.1.2. I have a question regarding transactions managed by the UndoManager.

Is it possible to delete the most recent transaction or a transaction with a specific name? After reviewing the API documentation (UndoManager | GoJS API), I couldn’t find a way to accomplish this. If there is a method to do so, I would greatly appreciate your guidance.

To provide some context, in the application I am developing, I want to remove unnecessary transactions that are registered during the initialization of GoJS-React. When the component mounts, an “initial merge” transaction occurs, but this transaction is not recorded by the UndoManager. Subsequently, when changes are made to the diagram, such as moving or adding nodes, a “merge data” transaction is generated and recorded by the UndoManager. Because of this “merge data” transaction, I have to perform two undo operations to roll back a single action, which is problematic.

If there is a way to remove the transaction corresponding to “merge data”, it would be extremely helpful.

Thank you in advance for your assistance.

When I run the gojs-react-basic sample and move a node, there is only one transaction recorded in the UndoManager. (To see its state, call myDiagram.undoManager.toString(2))

Yes, when the props state changes outside of the diagram, for example by editing the text of a node, there is a “merge data” transaction. But that is the only transaction, so undo and redo work as I believe you would expect.

Perhaps your code is not using the skipsDiagramUpdate property correctly?

Thank you for your response.

First, I want to clarify that I have not set the skipsDiagramUpdate property.

I monitored the records stored in the UndoManager in the console each time a model change was called, using the following code:

const diagramRef = React.useRef<ReactDiagram>(null);
const handleModelChange = React.useCallback((e: go.ChangedEvent) => {
  if (!e.isTransactionFinished) { return; }

  // Print transaction name
  const txnName = e.oldValue;
  console.log(txnName);

  // Print records in UndoManager
  const diagram = diagramRef.current?.getDiagram();
  if (diagram && diagram.undoManager) {
    console.log(diagram.undoManager.toString());
  }

  // ...
}, []);

The handleModelChange is set inside the initDiagram function as shown below:

diagram.addModelChangedListener(handleModelChange);

Immediately after initializing the diagram with the initial nodeDataArray and linkDataArray, I moved a node. The console output was as follows:

initial merge
UndoManager -1<0<=999[]
Move
UndoManager 0<1<=999[]
merge data
UndoManager 1<2<=999[]

As far as I can tell in my environment, the “merge data” transaction only occurs right after the initial setup. That is, it does not occur after the second operation (e.g., moving another node after the first node move).

Any advice or hints to resolve this issue would be greatly appreciated.

Thank you in advance.

If you don’t set skipsDiagramUpdate to true, it’s not surprising that you’re seeing a merge data transaction. As you sync your app state, you should be setting it to true to reflect that the GoJS model already has the change.

Also, I’m not sure why you’re adding a separate model change listener rather than using the prop built into the gojs-react component. I’d recommend taking a look at gojs-react-basic to get a feel for how applications are typically structured.