Clone entanglement when node data containing list is 2x instantiated from palette

Hello,

if the data underlying a node in a palette contains an array, and two instances of that node are dropped from the palette into the main diagram, then the arrays do not necessarily receive unique __gohashids, meaning that when using a binding to edit the values of elements in that list (via a TextBlock in an itemTemplate), a single edit may propagate to multiple nodes.

Here’s a MWE.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <script type="text/javascript" src="go-debug.js"></script>
</head>

<body>
  <div id="someDiv" style="border: solid 1px black; width:960px; height:640px"></div>
  <div id="paletteDiv" style="border: solid 1px black; width:960px; height:128px"></div>
  <script type="text/javascript" src="striptest.js"></script>
</body>
</html>

striptest.js

var GO = go.GraphObject.make;
function init() {
  myDiagram = GO(go.Diagram, "someDiv",
    { initialContentAlignment: go.Spot.Center, allowDrop: true }
  )
  myDiagram.nodeTemplateMap.add("test",
    GO(go.Node, "Auto",
      GO(go.Shape, "Rectangle", {fill:"white"})
      ,GO(go.Panel, "Vertical"
        ,GO(go.TextBlock, new go.Binding("text").makeTwoWay(), {editable:true})
        ,GO(go.Panel, "Table"
          ,new go.Binding("itemArray","xx")
          ,{ itemTemplate:
              GO(go.Panel, "TableRow"
                ,GO(go.TextBlock, new go.Binding("text","a").makeTwoWay(), {editable:true})
              )
          }
        )
      )
    )
  )
  myPalette = GO(go.Palette, "paletteDiv",
    {
      initialContentAlignment: go.Spot.Center,  // center the content
      nodeTemplateMap: myDiagram.nodeTemplateMap,  // share the templates used by myDiagram
      model: new go.GraphLinksModel([  // specify the contents of the Palette
        { category: "test", text: "hello", xx:[{"a":1},{"a":2}] }
      ])
    }
  )
}
init()

Drop two nodes onto the main diagram, and edit the text (works as expected) or edit a number (values are changed in both nodes). I think this is a bug.

This is quite a headache for me. Is this a problem you could address?

Copying node data objects does not make copies of any referenced objects (including Arrays) unless you either set Model.copiesArrays to true (and probably Model.copiesArrayObjects to true as well), or you provide a Model.copyNodeDataFunction to provide a custom copier to decide exactly what to share and what to copy.

http://gojs.net/latest/api/symbols/Model.html
http://gojs.net/latest/api/symbols/Model.html#copyNodeData

Oh, that’s great. Thanks for the reference.

For future reference, the properties copiesArray and copiesArrayObjects have to be set on the target diagram’s model, not on the source palette’s model.

I allow the user to clear and load new models occasionally – it feels inappropriate setting those copy-paste properties on the data model, and re-setting them every time the model changes. Please let me know if there’s a different way of making this setting.

If you are using Model.toJson and Model.fromJson, those properties should be persisted automatically.

If you are doing your own persistence, I’m sure you can handle it.

In any case you could just set those properties around the same time as setting Diagram.model.