Undo doesn't sync bindings

Stetps to reproduce the problem:

  1. move an object.
  2. press ctrl-z to undo the moving operation.
  3. the location binding is still the position after moving, not restoring to the one after undo.

Is this an expected behavior? Or is there a way to change the behavior (get data synchronized after undo)?

If I use diagram.moveParts() to move the undone parts, the properties get synchronized correctly.

If there is a TwoWay Binding on the Node.location or Node.position property, that should work. See, for example, Planogram.

In your app, how is the node moved? How is the location saved in the model? Are all changes occurring within a transaction?

There’s a twoway binding on node.location by a customized function, like

    new go.Binding("location", "", data => new go.Point(
      data.meta.locationX || 0,
      data.meta.locationY || 0
    )).makeTwoWay(
      (point, data) => {
        data.meta.locationX = point.x;
        data.meta.locationY = point.y;
      }
    ),

.

Moving nodes are synchronized correctly except undoing. When using debug version, there’re no warning messages about transactions. The history in undoManager recorded the moving. More importantly, the position of the part is changed.

If diagram.updateAllTargetBindings() is called, all undone parts will get its moved positions instead of the original one, where the latter is expected for undo.

I think your backwards conversion function isn’t complete. Please look at the example in the documentation: Binding | GoJS API

1 Like

Thanks! It works now.

model.set(...) is the key to solve the problem. Maybe the data binding could do some magic like vue’s reactive system via Object.defineProperty(...) so data binding will be automatically recorded. :)

As we recently found out the hard way, doing what Vue does automatically can have very bad unintended consequences. And programmers can implement updating property setters themselves. That is why GoJS model data are just plain JavaScript Objects.