Highlighting the same item in different tables

I’m trying to have shared objects between different nodes, where each node has an item array template defined.
Now, what I want is to have the same objects, but maybe different arrays in the node data.
E.g.
Node1: has data.items = [objA, objB, objC];
Node2: has data.items = [objA, objC];

Let’s say each object is 1 row in a node.
What I would like is that if an item is selected on one node, the selection is reflected on the other, and the row is highlighted on both nodes.
The only way I found that this can be done is with: diagram.updateAllTargetBindings() but that seems inefficient.
For some reason diagram.model.updateTargetBindings(item.data, '') doesn’t work. I assume that this is the result of the arrays being assigned different hash ids.

Is ther any more efficient solution to my use case? I could iterate over all the nodes, but that also seems slow for large diagrams. Also, I didn’t notice that there are any diagram event that might make this more efficient.

I think you could call Panel.findItemPanelForData and then call Panel.updateTargetBindings on the particular property that you are changing. That would be fairly efficient.

Here’s my test program. Note that unlike your situation I have made objA references in two separate Panel.itemArrays within the same Node, as well as in different Nodes. GoJS does not naturally support objects shared between Parts, although it does within one Part. And for that matter, neither do Model.toJson and Model.fromJson, because they will lose the sharedness of the references.

  function init() {
    var $ = go.GraphObject.make;

    myDiagram =
      $(go.Diagram, "myDiagramDiv",
          {
            initialContentAlignment: go.Spot.Center,  // for v1.*
            "undoManager.isEnabled": true
          });

    myDiagram.nodeTemplate =
      $(go.Node, "Vertical",
        $(go.TextBlock, new go.Binding("text")),
        $(go.Panel, "Auto",
          $(go.Shape, { fill: "white" }, new go.Binding("fill", "color")),
          $(go.Panel, "Horizontal",
            $(go.Panel, "Vertical", { name: "FIRST", padding: 6 },
              new go.Binding("itemArray", "items"),
              {
                itemTemplate:
                  $(go.Panel,
                    $(go.TextBlock,
                      new go.Binding("text"),
                      new go.Binding("stroke", "color"))
                  )
              }),
            $(go.Panel, "Vertical", { name: "SECOND", padding: 6 },
              new go.Binding("itemArray", "items"),
              {
                itemTemplate:
                  $(go.Panel,
                    $(go.TextBlock,
                      new go.Binding("text"),
                      new go.Binding("stroke", "color"))
                  )
              }),
          )
        )
      );

    var objA = { text: "objA" };
    var objB = { text: "objB" };
    var objC = { text: "objC", color: "red" };
    myDiagram.model = new go.GraphLinksModel(
    [
      { key: 1, text: "Alpha", color: "lightblue", items: [objA, objB, objC] },
      { key: 2, text: "Beta", color: "orange", items: [objA, objC] }
    ]);

    window.toggleColor = function() {
      myDiagram.commit(function(diag) {
        diag.model.set(objA, "color", (objA.color === "green" ? "black" : "green"));
        diag.nodes.each(function(n) {
          var first = n.findObject("FIRST");
          if (first) {
            var ipan = first.findItemPanelForData(objA);
            if (ipan) ipan.updateTargetBindings("color");
          }
          var second = n.findObject("SECOND");
          if (second) {
            var ipan = second.findItemPanelForData(objA);
            if (ipan) ipan.updateTargetBindings("color");
          }
        });
      }, "changed color");
    };
  }

Just call toggleColor to change the stroke color of all TextBlocks that are bound to objA's color property.

image

I ended up doing this:

diagram.nodes.each(n => {
    if(n.data.isTable){
        const obj = n.findObject('TABLE');
        n.data.items.forEach(el => {                               
             const ipan = obj.findItemPanelForData(el);
             ipan.updateTargetBindings('isSelected');
         });
     }
});

I tried to avoid iterating over n.data.items by trying to do something like:
obj.updateTargetBindings('items')
but that didn’t work. Anyway, I assume this is just as efficient.
Thanks Walter!

No, that is not as efficient, because you are calling Panel.updateTargetBindings for each item Panel.

So you tried something like:

diagram.nodes.each(n => {
    const obj = n.findObject("TABLE");
    if (obj) {
        const ipan = obj.findItemPanelForData(objA);
        if (ipan) ipan.updateTargetBindings("isSelected");
    }
});

where objA is the item data object that you modified?

Yes, but I need to deselect any previous selection made (only one item may be active at a time)

Ah, you didn’t mention that before. So you could look only for those Panels corresponding to data objects whose isSelected property has changed.

Thanks for your help walter. I just find the previously isSelected data object and update the target bindings accordingly.

You really need to respond to our email.