TextBlock conflicting with itemArray in a nodeTemplate

I am trying to programmatically import a process flow diagram from draw.io into GoJS, and I’ve run into a conflict between the TextBlocks and the itemArrays. Before adding the itemArray, the TextBlock renders exactly how I need it. After adding the itemArray, the TextBlock disappears. I’ve tried several different ways of ordering, formatting, nesting, and binding the two to no success. Here’s the nodeTemplate I’m using:

  myDiagram.nodeTemplateMap.add("Node",
    $(go.Node, "Spot",
      {
        locationObjectName: "SHAPE", selectionObjectName: "SHAPE", rotatable: true,
        mouseEnter: doMouseEnter, click: doClick, mouseLeave: doMouseLeave
      },
      new go.Binding("itemArray", "itemArray"),
      {
        itemTemplate:
          $(go.Panel, "Auto",
            $(go.Shape, "Circle", { desiredSize: new go.Size(1, 1), fill: "black", fromLinkable:true, toLinkable:true }),
            new go.Binding("portId", "portId"),
            new go.Binding("alignment", "", function(data, node) { return new go.Spot(data.x, data.y); }),
            new go.Binding("fromSpot", "", function(data, node) { return new go.Spot(data.x, data.y); }),
            new go.Binding("toSpot", "", function(data, node) { return new go.Spot(data.x, data.y); })
          )
      },
      new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
      $(go.Shape, "Circle",
        new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
        {
          name: "SHAPE", strokeWidth: 2,
          fill: $(go.Brush, "Linear", { 0: "gray", 0.35: "white", 0.7: "gray" })
        }),
      $(go.TextBlock,
        { alignment: go.Spot.Center, textAlign: "center", margin: 1 },
        new go.Binding("text").makeTwoWay())
    ));

And here is a sample of the .json I am importing the bindings from (it is created programmatically from a draw.io .xml file).

   {"key":"vX6fYtIgIG8C6GX4y9tb-8","category":"Node","pos":"281 300","text":"0","size":"20 20","itemArray":[{"portId":"N","x":"0.5","y":"0"},{"portId":"NE","x":"0.855","y":"0.145"},{"portId":"E","x":"1","y":"0.5"},{"portId":"SE","x":"0.855","y":"0.855"}, {"portId":"S","x":"0.5","y":"1"},{"portId":"SW","x":"0.145","y":"0.855"},{"portId":"W","x":"0","y":"0.5"},{"portId":"NW","x":"0.145","y":"0.145"}]},
    {"key":"tQ1Rfqdzyl8Z7qJ2ouWq-12","category":"Node","pos":"1720 220","text":"1","size":"20 20","itemArray":[{"portId":"N","x":"0.5","y":"0"},{"portId":"NE","x":"0.855","y":"0.145"},{"portId":"E","x":"1","y":"0.5"},{"portId":"SE","x":"0.855","y":"0.855"}, {"portId":"S","x":"0.5","y":"1"},{"portId":"SW","x":"0.145","y":"0.855"},{"portId":"W","x":"0","y":"0.5"},{"portId":"NW","x":"0.145","y":"0.145"}]},

Thanks for any help you can provide.

When you use a “Spot” Panel, there has to be a main element about which the other elements are aligned. Normally the main element is the first element of the panel.

I’m guessing that there used to be a TextBlock as the first element, but you didn’t replace it with a Panel when adding the Panel.itemArray binding and the itemTemplate.

You don’t show an image of what you are getting (although I could probably reconstruct that, given the data) nor do you show what you want instead.

The Shape called “SHAPE” should be the main element. I’ve included examples of before and after adding the itemArray:

Before adding Node.itemArray:
image

    myDiagram.nodeTemplateMap.add("Node",
    $(go.Node, "Spot",
      {
        locationObjectName: "SHAPE", selectionObjectName: "SHAPE", rotatable: true,
        mouseEnter: doMouseEnter, click: doClick, mouseLeave: doMouseLeave
      },
      new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
      $(go.Shape, "Circle",
        new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
        {
          name: "SHAPE", strokeWidth: 2,
          fill: $(go.Brush, "Linear", { 0: "gray", 0.35: "white", 0.7: "gray" })
        }),
      $(go.TextBlock,
        { alignment: go.Spot.Center, textAlign: "center", margin: 1 },
        new go.Binding("text").makeTwoWay())
    ));

After adding Node.itemArray:
image

    myDiagram.nodeTemplateMap.add("Node",
    $(go.Node, "Spot",
      {
        locationObjectName: "SHAPE", selectionObjectName: "SHAPE", rotatable: true,
        mouseEnter: doMouseEnter, click: doClick, mouseLeave: doMouseLeave
      },
      new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
      $(go.Shape, "Circle",
        new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
        {
          name: "SHAPE", strokeWidth: 2,
          fill: $(go.Brush, "Linear", { 0: "gray", 0.35: "white", 0.7: "gray" })
        }),
      new go.Binding("itemArray", "itemArray"),
      {
        itemTemplate:
          $(go.Panel, "Auto",
            $(go.Shape, "Circle", { desiredSize: new go.Size(1, 1), fill: "black", fromLinkable:true, toLinkable:true }),
            new go.Binding("portId", "portId"),
            new go.Binding("alignment", "", function(data, node) { return new go.Spot(data.x, data.y); }),
            new go.Binding("fromSpot", "", function(data, node) { return new go.Spot(data.x, data.y); }),
            new go.Binding("toSpot", "", function(data, node) { return new go.Spot(data.x, data.y); })
          )
      },
      $(go.TextBlock,
        { alignment: go.Spot.Center, textAlign: "center", margin: 1 },
        new go.Binding("text").makeTwoWay())
    ));

What I want is for the TextBlock to still be shown like the first image after adding the itemArray

The main element should be the Shape with the name “SHAPE.”

Before adding Node.itemArray:
image

    myDiagram.nodeTemplateMap.add("Node",
    $(go.Node, "Spot",
      {
        locationObjectName: "SHAPE", selectionObjectName: "SHAPE", rotatable: true,
        mouseEnter: doMouseEnter, click: doClick, mouseLeave: doMouseLeave
      },
      new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
      $(go.Shape, "Circle",
        new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
        {
          name: "SHAPE", strokeWidth: 2,
          fill: $(go.Brush, "Linear", { 0: "gray", 0.35: "white", 0.7: "gray" })
        }),
      $(go.TextBlock,
        { alignment: go.Spot.Center, textAlign: "center", margin: 1 },
        new go.Binding("text").makeTwoWay())
    ));

After adding Node.itemArray:
image

myDiagram.nodeTemplateMap.add("Node",
    $(go.Node, "Spot",
      {
        locationObjectName: "SHAPE", selectionObjectName: "SHAPE", rotatable: true,
        mouseEnter: doMouseEnter, click: doClick, mouseLeave: doMouseLeave
      },
      new go.Binding("location", "pos", go.Point.parse).makeTwoWay(go.Point.stringify),
      $(go.Shape, "Circle",
        new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
        {
          name: "SHAPE", strokeWidth: 2,
          fill: $(go.Brush, "Linear", { 0: "gray", 0.35: "white", 0.7: "gray" })
        }),
      new go.Binding("itemArray", "itemArray"),
      {
        itemTemplate:
          $(go.Panel, "Auto",
            $(go.Shape, "Circle", { desiredSize: new go.Size(1, 1), fill: "black", fromLinkable:true, toLinkable:true }),
            new go.Binding("portId", "portId"),
            new go.Binding("alignment", "", function(data, node) { return new go.Spot(data.x, data.y); }),
            new go.Binding("fromSpot", "", function(data, node) { return new go.Spot(data.x, data.y); }),
            new go.Binding("toSpot", "", function(data, node) { return new go.Spot(data.x, data.y); })
          )
      },
      $(go.TextBlock,
        { alignment: go.Spot.Center, textAlign: "center", margin: 1 },
        new go.Binding("text").makeTwoWay())
    ));

As you can see, the text disappears after adding the itemArray, all else held equal. What I want is for the text to still look the same as in the first image, after adding the itemArray.

I would organize the node according to the following outline:

Node, "Spot", with itemArray binding
    Panel, "Spot"  // this is the main element of the outer Spot panel
        Shape, "Circle", name: "SHAPE"
        TextBlock

But I’m still not sure exactly what kind of node template you want.

This worked perfectly, thanks. Could you provide/point me to an explanation on why you suggested this structure? I’ll be needing to implement other itemArrays in the future.

Well, setting Panel.itemArray will replace all of the elements of the panel, other than the “main” element if there is one. So if it’s a “Spot” panel and you want to have a variable number of elements that have their alignment bound, you better make sure that the first element is the “main” one. Which sounded/looked like a circular shape with some text. Because the “Spot” panel can have only one “main” element, you have to use a panel to hold the shape and the text. Besides, you want to control the relative positions/sizes of those two elements.

1 Like