Quantcast
Channel: GoJS - Northwoods Software
Viewing all articles
Browse latest Browse all 7069

Lazy makeTwoWay binding

$
0
0

@reinzor wrote:

Is there a way to make the two way binding only update when a transaction has finished?

I am testing with a vue component that holds the state. If I pass this state directly to the nodeArray, the web application is not able to keep up when a node is moved:


<!DOCTYPE html>
<html>

<head>
  <title>Performance two way binding</title>
  <meta charset="UTF-8">
</head>

<body onload="init()">
  <div id="app">
    <span id="myNumberOfNodes"></span>
    <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
    <pre v-text="diagramData.nodeDataArray" style="height: 300px; overflow: scroll"></pre>
  </div>

  <script src="go.js"></script>
  <script src="https://unpkg.com/vue"></script>
  <script id="code">
    function init() {
      myApp = new Vue({
        el: '#app',
        data: {
          diagramData: {
            nodeDataArray: [],
            linkDataArray: []
          }
        },
        mounted: function () {
          var $ = go.GraphObject.make;  // for conciseness in defining templates

          myDiagram =
            $(go.Diagram, "myDiagramDiv",  // create a Diagram for the DIV HTML element
              { // enable undo & redo
                "undoManager.isEnabled": true
              });

          // define a simple Node template
          myDiagram.nodeTemplate =
            $(go.Node, "Auto",  // the Shape will go around the TextBlock
              $(go.Shape, "RoundedRectangle", { strokeWidth: 2, fill: "white" }),
              $(go.TextBlock, { margin: 8 }, new go.Binding("text", "key")),
              new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify)
            );

          // but use the default Link template, by not setting Diagram.linkTemplate

          // create the model data that will be represented by Nodes and Links
          let numberOfNodes = 50000
          let width = parseInt(Math.sqrt(numberOfNodes))
          let spacing = 100
          for (let i = 0; i < numberOfNodes; ++i) {
            this.diagramData.nodeDataArray.push({ key: `Alpha${i}`, "location": `${(i % width) * spacing} ${parseInt(i / width) * spacing}` })
            this.diagramData.linkDataArray.push({ from: `Alpha${i}`, to: `Alpha${i + 1}` })
          }

          myDiagram.model = new go.GraphLinksModel(this.diagramData.nodeDataArray, this.diagramData.linkDataArray);
        }
      })
    }
  </script>
</body>

</html>

However, when I subscribe to the changed event and only update the vue state when a transaction is finished, it seems to work fine:


<!DOCTYPE html>
<html>

<head>
  <title>Performance on transaction finished update</title>
  <meta charset="UTF-8">
</head>

<body onload="init()">
  <div id="app">
    <span id="myNumberOfNodes"></span>
    <div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
    <pre v-text="savedDiagramData.nodeDataArray" style="height: 300px; overflow: scroll"></pre>
  </div>

  <script src="go.js"></script>
  <script src="https://unpkg.com/vue"></script>
  <script id="code">
    function init() {
      myApp = new Vue({
        el: '#app',
        data: {
          savedDiagramData: {
            nodeDataArray: [],
            linkDataArray: []
          }
        },
        mounted: function () {
          var $ = go.GraphObject.make;  // for conciseness in defining templates
          var app = this

          myDiagram =
            $(go.Diagram, "myDiagramDiv",  // create a Diagram for the DIV HTML element
              { // enab le undo & redo
                "undoManager.isEnabled": true,
                "ModelChanged": function (e) {
                  if (e.isTransactionFinished) {  // show the model data in the page's TextArea
                    // console.log('hi')
                    // app.savedDiagramData = JSON.parse(e.model.toJson())
                    increment = JSON.parse(myDiagram.model.toIncrementalJson(e))
                    if (increment.modifiedNodeData) {
                      increment.modifiedNodeData.forEach((d) => {
                        Object.assign(app.savedDiagramData.nodeDataArray[d.key], d)
                      })
                    }
                  }
                }
              });

          // define a simple Node template
          myDiagram.nodeTemplate =
            $(go.Node, "Auto",  // the Shape will go around the TextBlock
              $(go.Shape, "RoundedRectangle", { strokeWidth: 2, fill: "white" }),
              $(go.TextBlock, { margin: 8, editable: true }, new go.Binding("text", "key")),
              new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify)
            );

          // but use the default Link template, by not setting Diagram.linkTemplate

          // create the model data that will be represented by Nodes and Links
          let numberOfNodes = 50000
          let width = parseInt(Math.sqrt(numberOfNodes))
          let spacing = 100
          for (let i = 0; i < numberOfNodes; ++i) {
            this.savedDiagramData.nodeDataArray.push({ key: i, "location": `${(i % width) * spacing} ${parseInt(i / width) * spacing}` })
            this.savedDiagramData.linkDataArray.push({ from: i, to: i+1 })
          }

          let initialSavedDiagramData = JSON.parse(JSON.stringify(this.savedDiagramData))
          myDiagram.model = new go.GraphLinksModel(initialSavedDiagramData.nodeDataArray, initialSavedDiagramData.linkDataArray);
        }
      })
    }
  </script>
</body>

</html>

However, on the second option, I am not able to easily propagate the source state to the target state using updateTargetBindings since the target and the source are not referring to the same data.

Is it possible to make the target to source update (twoWayBinding) somewhat lazy so that it only updates the state when a transaction has finished?

Thanks!

Posts: 3

Participants: 2

Read full topic


Viewing all articles
Browse latest Browse all 7069

Trending Articles