Conditionally showing Picture if data.source is present

Hi Team and @walter ,
I want to add the image if the property image is available in data model, else i would like to show the text.

I have added image to the node template. The image is getting reflected in all the nodes. How do we conditionally render images and text.

<!DOCTYPE html>
<html>
<head>
  <title>Banded LayeredDigraph Sample</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>

  <script src="https://unpkg.com/gojs"></script>
  <script src="https://gojs.net/extras/BandedLayeredDigraphLayout.js"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      layout: $(BandedLayeredDigraphLayout, { direction: 90, setsPortSpots: false }),  // custom layout is defined above
      "undoManager.isEnabled": true
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    { fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides },
    $(go.Shape,
      { fill: "white" },
      new go.Binding("fill", "color")),
    $(go.TextBlock,
      { margin: 8 },
      new go.Binding("text")),
      $(go.Picture, imageUrl)
  );

myDiagram.linkTemplate =
  $(go.Link,
    { routing: go.Link.AvoidsNodes, corner: 5 },
    $(go.Shape, { strokeWidth: 2 },
      new go.Binding("stroke", "color")),
    $(go.Shape, { toArrow: "Standard", strokeWidth: 0 },
      new go.Binding("fill", "color"))
  );

myDiagram.groupTemplate =
  $(go.Group, "Auto",
    { layout: $(go.LayeredDigraphLayout, { alignOption: go.LayeredDigraphLayout.AlignAll, setsPortSpots: false }) },
    { avoidable: false, fromSpot: go.Spot.AllSides, toSpot: go.Spot.AllSides },
    $(go.Shape, "RoundedRectangle",
      { parameter1: 20, fill: "transparent" }),
    $(go.Placeholder, { padding: 10 })
  );

// There should be at most a single object of this category.
// This Part will be modified by commitLayers to display visual "bands"
// where each "layer" is a layer of the graph.
// This template is parameterized at load time by the HORIZONTAL parameter.
// You also have the option of showing rectangles for the layer bands or
// of showing separator lines between the layers, but not both at the same time,
// by commenting in/out the indicated code.
const HORIZONTAL = false;
myDiagram.nodeTemplateMap.add("Bands",
  $(go.Part, "Position",
    new go.Binding("itemArray"),  // Array of band descriptor objects
    {
      isLayoutPositioned: false,  // but still in document bounds
      locationSpot: new go.Spot(0, 0, HORIZONTAL ? 0 : 146, HORIZONTAL ? 46 : 0),  // account for header height/width
      layerName: "Background",
      pickable: false,
      selectable: false,
      itemTemplate:
        $(go.Panel, HORIZONTAL ? "Vertical" : "Horizontal",
          { visible: false },  // hide bands without nodes or vertexes in them
          new go.Binding("visible", "bounds", b => b.width > 0 && b.height > 0),
          new go.Binding("position", "bounds", b => b.position),
          $(go.Panel, "Auto",  // the header
            new go.Binding("desiredSize", "bounds", r => HORIZONTAL ? new go.Size(r.width, 46) : new go.Size(146, r.height)),
            $(go.Shape, { fill: "transparent", strokeWidth: 0 }),
            $(go.TextBlock,
              { font: "bold 14pt sans-serif" },
              new go.Binding("text"))
          ),
          $(go.Panel,
            // option 1: rectangular bands:
            $(go.Shape,
              { fill: "transparent", strokeWidth: 0 },
              new go.Binding("desiredSize", "bounds", r => r.size),
              new go.Binding("fill", "color")),
            // option 2: separator lines:
            (HORIZONTAL
              ? $(go.Shape, "LineV",
                  { stroke: "#AAAAAA", alignment: go.Spot.TopLeft, width: 1 },
                  new go.Binding("height", "bounds", r => r.height),
                  new go.Binding("visible", "itemIndex", i => i > 0).ofObject())
              : $(go.Shape, "LineH",
                  { stroke: "#AAAAAA", alignment: go.Spot.TopLeft, height: 1 },
                  new go.Binding("width", "bounds", r => r.width),
                  new go.Binding("visible", "itemIndex", i => i > 0).ofObject())
            )
          )
        )
    }
  ));


myDiagram.model = new go.GraphLinksModel(
  [
    { key: "_BANDS", category: "Bands",
      itemArray: [
        { index: 0, text: "Lane1", color: "lightblue" },
        { index: 1, text: "Lane2", color: "lightgreen" },
        { index: 2, text: "Lane3", color: "lightyellow" },
      ]
    },
    { key: 1, text: "App1", appType: "App Type 1", info: "Information", color: "#B2DFDB", state: "one", loc: "0 0", band: "Lane1", imageUrl: "./assets/image.png" },
    { key: 2, text: "App 2", appType: "Payment Application", info: "Payment App", color: "#B2B2DB", state: "two", password: "1234", loc: "0 100", band: "Lane1" },
    { key: 34, isGroup: true, band: "Lane2" },
    { key: 3, text: "A Folder", color: "#1DE9B6", state: 2,  flag: false, choices: [1, 2, 3, 4, 5], group: 34 },
    { key: 4, text: "B Folder", color: "#1DE9B6", state: 2,  flag: false, choices: [1, 2, 3, 4, 5], group: 34 },
    { key: 41, text: "C Folder", color: "#1DE9B6", state: 2,  flag: false, choices: [1, 2, 3, 4, 5], group: 34 },
    { key: 5, text: "Services", color: "#1DE9B6", state: 2,  flag: false, choices: [1, 2, 3, 4, 5], band: "Lane2" },
    { key: 6, text: "ED Services", color: "#00BFA5", state: "three", flag: true, band: "Lane3" },
    { key: 7, isGroup: true, band: "Lane2" },
    { key: 8, text: "A Folder", color: "#1DE9B6", state: 2, flag: false, choices: [1, 2, 3, 4, 5], group: 7 },
    { key: 9, text: "B Folder", color: "#1DE9B6", state: 2,  flag: false, choices: [1, 2, 3, 4, 5], group: 7 },
    { key: 10, text: "Services", color: "#1DE9B6", state: 2,  flag: false, choices: [1, 2, 3, 4, 5], band: "Lane2" },
    { key: 11, text: "ED Services", color: "#00BFA5", state: "three", flag: true , band: "Lane3"},
  ],
  [
    { from: 1, to: 5, color: "#5E35B1" },
    { from: 3, to: 4, color: "#6200EA" },
    { from: 3, to: 5, color: "#6200EA" },
    { from: 3, to: 41, color: "#6200EA" },
    { from: 4, to: 41, color: "#6200EA" },
    { from: 1, to: 6, color: "#5E35B1" },
    { from: 2, to: 10, color: "#5E35B1" },
    { from: 8, to: 9, color: "#6200EA" },
    { from: 8, to: 10, color: "#6200EA" },
    { from: 9, to: 10, color: "#6200EA" },
    { from: 2, to: 11, color: "#5E35B1" }
  ]);
  </script>
</body>
</html>```

Here’s an example. The basic idea is to make the Picture not visible by default, but have a Binding so that if the data property is present, it make it visible after all. The opposite thing could happen for the TextBlock.

<!DOCTYPE html>
<html>
<head>
  <title>Minimal GoJS Sample</title>
  <!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
  <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
  <textarea id="mySavedModel" style="width:100%;height:250px"></textarea>

  <script src="https://unpkg.com/gojs"></script>
  <script id="code">
const $ = go.GraphObject.make;

const myDiagram =
  $(go.Diagram, "myDiagramDiv",
    {
      "undoManager.isEnabled": true,
      "ModelChanged": e => {     // just for demonstration purposes,
        if (e.isTransactionFinished) {  // show the model data in the page's TextArea
          document.getElementById("mySavedModel").textContent = e.model.toJson();
        }
      }
    });

myDiagram.nodeTemplate =
  $(go.Node, "Auto",
    { width: 120, height: 120 },
    $(go.Shape, { fill: "white" },
      new go.Binding("fill", "color")),
    $(go.Picture, { visible: false, width: 100, height: 100 },
      new go.Binding("visible", "src", src => !!src),
      new go.Binding("source", "src")),
    $(go.TextBlock, 
      new go.Binding("visible", "src", src => !src),
      new go.Binding("text", "text"))
  );

myDiagram.model = new go.GraphLinksModel(
[
  { key: 1, text: "Alpha", color: "lightblue", src: "https://gojs.net/latest/samples/images/hs1.jpg" },
  { key: 2, text: "Beta", color: "orange", src: "https://gojs.net/latest/samples/images/nonexistent.jpg" },
  { key: 3, text: "Gamma", color: "lightgreen" },
  { key: 4, text: "Delta", color: "pink" }
],
[
  { from: 1, to: 2 },
  { from: 1, to: 3 },
  { from: 2, to: 2 },
  { from: 3, to: 4 },
  { from: 4, to: 1 }
]);
  </script>
</body>
</html>

Note that you said that it should show the image if the data property is present. Notice how the Picture is visible but empty in the case of a non-existent URL.

Whereas for nodes “Gamma” and “Delta”, the text continues to show because the corresponding data.src properties don’t exist.

If you want to handle error conditions for loading images, you can either do what is done in Get Started with GoJS or you could implement a Picture.errorFunction event handler or a Picture.successFunction event handler.