Inconsistent setDataProperty

I’m going crazy here.

I’m using setDataProperty with a custom, data-inspector-like sidebar. Updating an input in the side bar updates a node in the diagram associated with the information currently displayed in the sidebar.

I have, from what I can tell, two identically-coded inputs. One successfully updates the data model. One doesn’t. I cannot, for the life of me, figure out why.

Is there something specific to GoJS that’s going on here?
Am I just missing something?

Relevant Code Bits

 function init() {
    var $ = go.GraphObject.make;

    //------------------- Define Diagram Properties -------------------
    myDiagram =
      $(go.Diagram, "myDiagramDiv", 
        {
          "undoManager.isEnabled": true,
          "toolManager.hoverDelay": 10,
          "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,
          layout: $(go.ForceDirectedLayout, { defaultSpringLength: 10 }),
        });
    
    //------------------- node template common parts -------------------
    function commonGroupStyle() {
      return [
        {
          selectionAdorned: false, // this line removes the blue rectangle around selected objects
          shadowOffset: new go.Point(0, 0),
          shadowBlur: 10,
          shadowColor: "blue",
          click: fillInfoBox  //FILLS MY CUSTOM DATA-INSPECTOR-LIKE SIDEBAR
        },
      ]
    }
    function commonShapeStyle() {
      return [
        {
          name: "NODESHAPE",
          fill: "lightgray",
          stroke: "darkslategray"
        },
      ];
    }
    function commonTextBlock() {
      return $(go.TextBlock,
        new go.Binding("text", "label").makeTwoWay(), //DOES MY PROBLEM INVOLVE THIS?
        {
          name: "NODELABEL",
          stroke: "darkslategray",
          margin: 10
        }
      );
    }

    //------------------- group templates -------------------
    var basicTemplate =
      $(go.Group, "Auto", commonGroupStyle(),
        $(go.Shape, "RoundedRectangle", commonShapeStyle()), 
        commonTextBlock()
      );
    var projectTemplate =
      $(go.Group, "Auto", commonGroupStyle(),
        $(go.Shape, "Rectangle", commonShapeStyle()), 
        commonTextBlock()
      );

    myDiagram.groupTemplateMap.add("concept", basicTemplate);
    myDiagram.groupTemplateMap.add("project", projectTemplate);

    //------------------- link template common parts -------------------
    function commonLinkStyle() {
      return [
        { relinkableFrom: true, relinkableTo: true }
      ]
    }

    //------------------- link templates -------------------
    myDiagram.linkTemplate = //taken from the conceptMap example
      $(go.Link,  // the whole link panel
        commonLinkStyle(),
        $(go.Shape,  // the link shape
          { stroke: "black" }),
        $(go.Shape,  // the arrowhead
          { toArrow: "standard", stroke: null }),
        $(go.Panel, "Auto",
          $(go.Shape,  // the label background, which becomes transparent around the edges
            {
              fill: $(go.Brush, "Radial", { 0: "rgb(240, 240, 240)", 0.3: "rgb(240, 240, 240)", 1: "rgba(240, 240, 240, 0)" }),
              stroke: null
            }),
          $(go.TextBlock,  // the label text
            {
              textAlign: "center",
              font: "10pt helvetica, arial, sans-serif",
              stroke: "#555555",
              margin: 4,
              text: "WHATEVER"
            },
            new go.Binding("text", "label").makeTwoWay())
        )
      );

    //------------------- select model -------------------
    //GETMODEL FUNCTION WORKS FINE, ITS CODE IS EXCLUDED HERE BECAUSE 
    //IT'S LONG AND IS ONLY USED FOR INITIALIZING THE DIAGRAM
    myDiagram.model = go.Model.fromJson(getModel("tester")); 

  } //End Init

  //WRITES DATA INPUT INTO THE DATA-INSPECTOR-LIKE SIDEBAR BACK TO THE MODEL
  function writeBack(key, property, value){
    var node = myDiagram.findNodeForKey(key);
    myDiagram.startTransaction('set new node property');        
    console.log(node.data);
    console.log(`Attempting to set ${property} on node with key ${key} to ${value}`);
    myDiagram.model.setDataProperty(node, property, value);
    console.log(node.data);
    myDiagram.commitTransaction('set new node property')
  }

  //FILLS IN MY CUSTOM DATA-INSPECTOR-LIKE SIDEBAR
  function fillInfoBox(e, o){
    //obtain data reference using the object
    const d = o.part.data
    
    //set hidden ID & title
    document.getElementById("info-id").textContent = d.key;
    //THESE NEXT THREE LINES DON'T WORK
    var title = document.getElementById("info-title");
    title.value = d.label;
    title.onchange = function(){writeBack(d.key, "label", title.value)}
    //THESE NEXT THREE LINES DO WORK
    var type = document.getElementById("type");
    type.value = d.category;
    type.onchange = function(){writeBack(d.key, "category", type.value)}
  }

Here’s the console after updating the “type” input (which works), then updating the “info-title” input (which does not work):

image

Notice “category” updates to the model just fine, but “label” doesn’t update at all.

What I’m doing seems simple enough… I’m going crazy trying to figure out why “category” gets set just fine, yet “label” refuses to update?
Does it have something to do with the fact that I’ve used Label as a binding in my diagram?

Any help would be greatly appreciated.

Are both “info-title” and “type” HTMLTextAreaElements?

They are both “input” elements. Included below.
Excuse my div soup - I threw some comments in to make them more visible.

<div id="diagram-holder" style="width: 100%; display: flex; justify-content: space-between; border: solid;">
  <div id="myDiagramDiv" style="flex-grow: 1; height: 750px;"></div>
  <div id="side-panel">
    <!-- INFO-TITLE INPUT -->    
    <input id="info-title"></input>
    <div id="info-id" hidden= true></div>
    <div id="common-attributes" class="common-attributes">
      <div id="common-attributes-head" class="section-head">Common Attributes:</div>
      <div class="data-point">
        <div class="side-panel-label">Type</div>
        <!-- TYPE INPUT -->
        <input id="type" class="side-panel-value"></input>
      </div>
      <div class="data-point">
        <div class="side-panel-label">Links in View</div>
        <div id="view-links" class="side-panel-value" style="font-style: italic;"></div>
      </div>
      <div class="data-point">
        <div class="side-panel-label">Links in Model</div>
        <div id="model-links" class="side-panel-value" style="font-style: italic;"></div>
      </div>
    </div>      
    <div id="type-attributes-head" class="type-attributes section-head">
      <div>Type Attributes:</div><button id="add-type-attribute" class="add-button" onclick=addTypeAttribute()>+</button>
    </div>
    <div id="type-attributes" class="type-attributes">
      Select a node
    </div>
    <div id="view-attributes-head" class="view-attributes section-head">
      <div>View Attributes:</div><button id="add-view-attribute" class="add-button" onclick=addViewAttribute()>+</button>
    </div>
    <div id="view-attributes" class="view-attributes">
      Select a node
    </div>
  </div>  
</div>

You can see a lot of groundwork laid for future features… which is why I’m wanting to use a fully-custom data-inspector-like approach. But man, this first bit is really throwing me for a loop.

Wait – why are you passing a Node to Model.setDataProperty. You are explicitly outputting node.data to the console. You should be passing node.data to Model.set.

1 Like

UGH

Thank you.

Changing “node” to “node.data” fixed it.

Lessons learned: I didn’t check my types well enough against the documentation.

Strange that the Category one was working at all. The fact that it worked made me stop looking so hard at the setNodeData function itself. I suspect it may have to do with the “nodeCategoryProperty” caveat in the linked documentation.

Thanks again!

That’s because Part.category is related to data.category, although it’s not a Binding.

Also, if you were using go-debug.js, you would have gotten console warnings about Model.set setting properties on GraphObjects.

Hmm. I am using go-debug.js & didn’t see any such warnings.

image

I’m quite confident it’s still something I’m doing wrong - but I wanted to see if there was something preventing that warning.

:-/

In go-debug.js, the Model.setDataProperty code only issues the warning once, the first time it sees such a situation. However it does not issue that warning if you constructed the Model.nodeDataArray holding instances of Nodes or other GraphObjects, in case you really do want to have a diagram about diagram parts.