@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
updateTargetBindingssince 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