How to set color of links based on BOTH nodes?

I have an attribute on nodes as “severity” of type int. This number is mapped to a color. For example 4 is red, 5 is blue.
Now, I’m looking for a way to get the “severity” of both nodes and compare them as numbers, take the bigger number and set it’s associated color to the link between the two nodes.
For example, if node1.severity = 3 and node2.severity = 5, the link that is connecting these two nodes, must be blue, because 5 is bigger than 3 and 5 represents blue.
I was thinking I’ll use dataBinding to do that.
Now I already found this code:
https://gojs.net/latest/samples/productionProcess.html

// mark each Shape to get the link geometry with isPanelMain: true
          $(go.Shape, { isPanelMain: true, stroke: "gray", strokeWidth: 10 },
            // get the default stroke color from the fromNode
            new go.Binding("stroke", "fromNode", function(n) { return go.Brush.lighten((n && Colors[n.data.color]) || "gray"); }).ofObject(),
            // but use the link's data.color if it is set
            new go.Binding("stroke", "color", colorFunc)),

Using the idea above, I might be able to do similar thing, binding the "stroke" to "fromNode" and access it’s severity. But my question is, how I can access the "toNode" as well?
To put it simple, I’m looking for something like this:

// the code below is not valid, it's just something I'm hoping to be able to implement.
 new go.Binding("stroke", ["fromNode", "toNode"], function(n, m) { return go.Brush.lighten((n && m && decideFinalColor(n.data.severity, m.data.severity)) || "gray"); }).ofObject(),

Any suggesstion?

Bindings really only work within the scope of the binding – in this case within the Link. If some other Part (in this case either Node) changes, there will not be any automatic updating of any Bindings on this Link. So that would be a problem even if your color determination depended on only one connected node. The example you found works because the color does not change.

You could use a source property name that is the empty string, in which case the ofObject Binding conversion function will receive the Link as the argument. But note that initially both Link.fromNode and Link.toNode will be null before the link is connected with nodes.

Then once all of the links have been loaded, you can force all of their bindings to be evaluated again by calling https://gojs.net/latest/api/symbols/Part.html#updateTargetBindings on each Link. You could do that in an “InitialLayoutCompleted” DiagramEvent listener, iterating over the e.diagram.links. And whenever you change any node’s data’s color property, you could call updateTargetProperties on all connected links, node.linksConnected.

Thanks.
I’m not sure I understood this part:

So basically, I should add another property to the links, called color for example.
Then every time any of the connected nodes changed color, I should manually calculate the correct color for the link, and set the color property of the link, and then update the diagram so the changes will take effect, am I right?

Does the “severity” of your nodes change?

If so, it would probably be simplest if after such changes have happened that you just iterate through all of the Diagram.links and you just update the link.path.stroke to be the color that you want based on the link.fromNode.data.severity and the link.toNode.data.severity.

Be sure to perform that iteration within the same transaction that you are modifying the node.data.severity properties.

Basically I am saying that in the general case it might be simplest to not try to use a Binding in a situation where it doesn’t make sense because it’s depending on the values of other Parts.

1 Like