Changing category inside a template binding

I have a situation where, depending on the length property of a node, I want to display different templates.

Since this width can change via tools and updates to the node’s data, I have a binding on my template:

new go.Binding("width", "", (nodeData) => {
   if(nodeData.length === 0)
      this.diagram.model.setCategoryForNodeData(nodeData, "SmallTemplate");
   return nodeData.length;
}

I have the inverse logic on my other template (model.length > 0).

What happens is the correct template is chosen initially, and the template will change once when I update the length property, but then the template will never change again, even though I can step through the binding code in my debugger.

Is there a better way to do this?

As mentioned in GoJS Data Binding -- Northwoods Software and specified in Binding | GoJS API, Binding conversion functions must not have any side-effects. (Well, at least not any that matter to the binding system.)

And in any case, switching templates at that point can result in odd behaviors, as bindings can be evaluated in any order or any number of times.

So it’s better to improve the way that the category is chosen from the node data object. One way to do that is by customizing the Model.nodeCategoryProperty to be a function instead of just a property name. For example, whenever about to load a model:

    var model = . . .;  // do the usual initialization of model data
    model.nodeCategoryProperty = function(data) {
      if (typeof data.width === "number" && data.width <= 0) return "SmallTemplate";
      return data.category;
    };
    myDiagram.model = model;

Will this function fire when width changes after the model has been loaded?

Sorry – I forgot about the main point of your question. No, what I described won’t help you then.

I hope it makes sense why choosing a template cannot be done via a binding, because it would change the set of GraphObjects and Bindings while a binding was being evaluated.

You’ll need to do what I think you were going to do next anyway: call Model.setCategoryForNodeData whenever you set the data.width property from non-zero to zero or from zero to non-zero.

Yeah, I understand why it’s bad to do inside a template binding. I knew it wasn’t a great solution, but wasn’t sure of a better place to do it in a “GoJS Way”. Thanks!