Binding category to shape fill colour. Undo doesn't work visually

GoJS v1.7.11 - Chrome

I need to change the category value dinamically.

The code:

diagram.startTransaction('changing state: ' + node.data.text);
model.setDataProperty(node.data, 'category', 'stateInitial');            
diagram.commitTransaction('changing state: ' + node.data.text);

Node Template:

$(go.Shape, 'RoundedRectangle',
    { stroke: null , strokeWidth: 0 },
    new go.Binding("fill", "category", function(category){

         if( category == 'stateInitial'){
              return '#99AE3B';
          }
          else if(category == 'stateFinal'){
              return '#E53935';
          }
          return '#6699CC';
      })
    ), . . .

This works OK, the node change its colour dinamcally.

But, After doing this:
diagram.undoManager.undo();

The node switch to previous category in the model (this is OK) but I don’t see the change of colour back to the previous colour. Only diagram.rebuildParts() method works, but I can’t use it.

Any idea?

The order in which bindings are evaluated is not defined, and when you combine that with replacing the template for a data object, things can be very confusing.

It is not natural to have a Binding source be the “category”. Typically, such bindings are not needed because it is more natural to just “evaluate” the binding manually, inlining any values when you define the template.

myDiagram.nodeTemplateMap.add("one",
  $(go.Node, "Auto",
    $(go.Shape, { fill: "red", ... }),
    . . .));

myDiagram.nodeTemplateMap.add("two",
  $(go.Node, "Auto",
    $(go.Shape, { fill: "green", ... }),
    . . .));

will ensure that when data.category === "one", the shape will be “red” and when data.category === "two", the shape will be “green”.

I think this is much clearer than trying to do:

function determineColor(c) {
  if (c === "one") return "red";
  if (c === "two") return "green";
  return "blue";
}

myDiagram.nodeTemplateMap.add("one",
  $(go.Node, "Auto",
    $(go.Shape, { ... },
      new go.Binding("fill", "category", determineColor)),
    . . .));

myDiagram.nodeTemplateMap.add("two",
  $(go.Node, "Auto",
    $(go.Shape, { ... },
      new go.Binding("fill", "category", determineColor)),
    . . .));

Perhaps your problem, other than having bindings on the category at all, is because you don’t have the same (or at least consistent) bindings in all of the templates?

Thanks for the repply.

I want to reuse the same node template

nodeTemplateMap.add("stateInitial", nodeTpl);
nodeTemplateMap.add("state", nodeTpl);
nodeTemplateMap.add("stateFinal", nodeTpl);

This is because the only change is the fill colour. I need only a repaint, because the model undo ok.

If the only difference between the three node types is a color, then it would be simpler to just have a single template with a binding for the color.

You can even use the “category” property with those three string values, if you set Model.nodeCategoryProperty to be “” (the empty string) or to a property name that your data do not use at all. This assumes that you don’t have yet other categories and templates.

Ok, thank you!
Regards