Binding from both part data and model data


We have a colour variable which is stored in the diagram.modelData which we bind into a part using something like this:

new Binding('stroke', 'areaBackgroundColor').ofModel()

However, we would also like the ability to override this stroke value with a hover/select colour when the user moves their mouse over this part and also set the colour value when the part is selected. We previously used something like the following to achieve this (also combined with mouseEnter & mouseLeave events to do the hover:

new Binding('stroke', 'isSelected', selected => selected ? 'dodgerblue' : 'green').ofObject()

These two bindings are from different models and as far as I can see you cant really have two separate bindings for this side by side. Is there a way of being able to bind from both the diagrams modelData and the parts data at the same time so that we can react to changes in both these places and set the one property accordingly?

You can have multiple Bindings that target the same property with different source properties. But it sounds like you should have a single Binding (not ofModel) whose source property is the empty string. The conversion function will get the node data object as the first argument, so you can look at all of its properties, and the Shape as the second argument, so you can look at all of its properties, including its GraphObject.part for its Part.isSelected, and its GraphObject.diagram for its Diagram.model.

After trying this it does not seem like the binding updates when isSelected changes nor if the modelData changes?

              new Binding('stroke', '', (data, shape) => {
                console.log('binding updated', data, shape.part.isSelected);

                return 'white';

This is if I have read your message correctly though… I can access the properties in both the part and the model, but they are not triggering the binding when they update.

Hmmm, maybe you do want to keep the two Bindings, one ofModel and one ofObject, but have them use smarter conversion functions that use the second argument to decide whether to use the property value or something else.

Seems like it,

              new Binding('stroke', 'areaBackgroundColor', (color, shape: Shape) =>
                shape.part?.isSelected ? TextColor.Selected : color
              new Binding('stroke', 'isSelected', (selected, shape: Shape) =>
                selected ? TextColor.Selected : shape.diagram?.model?.modelData?.areaBackgroundColor

Seems to work