I’m using react and gojs and I implemented a GraphLinksModel that fits perfectly my needs.
I’m using the contextMenu and after clicking on a button, if this is the root, I clear all the children then I add new ones.
This is the relative code:
//function for clearing nodes and links
removeNodesAndLinks = nodeId => {
const nodes = myDiagram.model.nodeDataArray
if (nodeId === 1 && nodes.length > 1) {
nodes.filter(node => node.NodeId !== 1).forEach(n => {
// remove links by selection
const node = myDiagram.findNodeForKey(n.key)
myDiagram.selectCollection(node.findLinksConnected())
myDiagram.commandHandler.deleteSelection()
//remove nodes
myDiagram.model.removeNodeData(n)
})
}
}
//this is the addChild function
const addChild = newnode => {
const selnode = myDiagram.selection.first()
if (!(selnode instanceof go.Node)) return
myDiagram.startTransaction("add node and link")
myDiagram.model.addNodeData(newnode)
const newlink = { from: selnode.data.key, to: newnode.NodeId }
myDiagram.model.addLinkData(newlink)
myDiagram.commitTransaction("add node and link")
}
//this is the add new nodes function
const addNodes = data => {
data.forEach(node => {
addChild(node)
})
}
PROBLEM
If I run addNodes or removeNodesAndLinks one by one, they work perfectly, but if I run the remove and subsequently the add Nodes as I do in the button action it works only the removing phase and not the adding phase.
This is the code in which I create the button and add the action:
this.makeButton(
"NameA",
(e, obj) => {
const contextmenu = obj.part
const nodedata = contextmenu.data
this.removeNodesAndLinks(nodedata.NodeId)
this.fetchTheData("NameA") //after the fetch it run addNodes
},
// visiblePredicate
)
Maybe the problem is that this piece of code, must implement the fetch data function as a callback or as an async/await function?
Your removeNodesAndLinks function seems very inefficient because it is doing repeated transactions due to your calls to a command (the CommandHandler.deleteSelection method). Not to mention that that command will remove the node from the model data for you already, so your call to Model.removeNodeData should be a no-op.
If you are going to remove everything from the model except for one node, I would think it would be easier to replace the Diagram.model with a new model whose only Model.nodeDataArray contents is the one node data object that you wanted to keep. Something like:
const arr = [];
const rootdata = myDiagram.model.findNodeDataForKey(nodeId);
if (rootdata) arr.push(rootdata);
myDiagram.model = new go.GraphLinksModel(arr);
Your addNodes function suffers from the same problem of performing repeated transactions rather than just a single transaction that surrounds the whole loop. (But nested transactions are OK, in case you want to call addChild independently.)
Dear Walter,
due to your help my code became faster.
I replaced the model leaving only the root node in the removeNodesAndData and then in the addNodes function I used addNodeDataCollection and addLinkDataCollection like this: