Applying effect to nodes that are not selected

I want to apply effects (basically just a change in the fill) to all nodes which are not part of the diagram’s selection, but only when the diagram has at least one node selected. I’ve tried binding to isSelected…

    new go.Binding('fill', 'isSelected', (selected, obj: go.Part) => {
      const shouldHighlight = // ... logic for highlighting
      return shouldHighlight ? getHighlightColor(myColor, obj.part) : myColor

…which seems to fire when the node itself has its selection changed, but not when other nodes’ selection changes. What’s an appropriate way to apply these highlights to a node when the selection of another node changes?

Do I need to keep track in the diagram’s ChangedSelection handler and apply changes to the model that I can then bind to? Or is there a better way?


Some things aren’t naturally appropriate for data binding. You have discovered one such case.

It might be easier to implement a “ChangedSelection” DiagramEvent listener that modifies the Shape.fill of the appropriate Shape in all of the Nodes according to whether the Diagram.selection is empty or not as well as whether the node is Part.isSelected.

Ah, thanks. This makes sense. Also, it turns out I only had to set the opacity for the effect I wanted, which made it quite simple to do all this within ChangedSelection.

Another thought: you probably don’t want to save any state in the model when making these changes due to selection. If that is the case, and I would expect that normally to be the case, then you probably want to make all of those changes while Diagram.skipsUndoManager is temporarily true.

You can either just set the skipsUndoManager property twice or you could, more safely, call Diagram.commit and have the second argument be null.

Yeah, thanks, I agree. My original idea of using the data binding seems to have relied on doing this, but it did seem needlessly noisy. Just iterating over the nodes and directly applying the correct opacity based on my current selection seems to have done the job nicely.