Updating Diagram with new loaded Array

I am using GoJs v2.1.42 in combination with Electron and NodeJs on Windows10.

Is there any possible way to update the whole GoJs Diagram after the side has got new Arrays for NodeDataArray and Link Data Array?

The Website asks in specific time periods for new data. If the data got changed it overwrites the old data, which can be also the data for the Diagram. How can I manually update the Diagram via a js function, after updating the data?


Code example:

function data_update(new_data){
   if(old_data != new_data){
      old_data = new_data;
      update_diagram();
   }
}

How should the update_diagram term be written?

I have searched through other topics, but none of them have worked, nor have I found a really suitable solution.

If you expect there to be incremental changes to the node and link data:

myDiagram.model.commit(m => {
  m.mergeNodeDataArray(newNodeDataArray);
  m.mergeLinkDataArray(newLinkDataArray);
});

Please read GraphLinksModel | GoJS API

If the new data is unrelated to the model that the diagram is showing, just create a new model and assign Diagram.model.

The following function shows how the tree ist generated:

function render(){    
    var DIA = go.GraphObject.make;
    myDiagram = DIA(go.Diagram, "tree", { ...  layout: DIA(go.TreeLayout, { ... }),  } );

    var nodeDataArray = array_data;
    var linkDataArray = array_linkdata;

    myDiagram.model = new go.GraphLinksModel(nodeDataArray,linkDataArray);
    myDiagram.nodeTemplate = DIA(go.Node, "Auto", ... );
    myDiagram.linkTemplate = DIA(go.Link, ... );
}

Where do I include your given function?
How can I call it?

I tried to include it into the data_update() function and into the shown render() function.
Both had thrown an error:

What could I try else?

It’s more efficient if you fully initialize the Diagram ignoring the model and then assign the Diagram.model last. Assigning templates will cause those Parts to be removed and re-created, but if you do it earlier there presumably aren’t any Nodes or Links to be re-built.

Is this using React? Constantly re-rendering is rather wasteful, especially if you have large or complicated diagrams. You might want to read GoJS and React -- Northwoods Software and use the gojs-react package. If you look at the code you can see how it calls Model.mergeNodeDataArray and GraphLinksModel.mergeLinkDataArray. Yes, as documented, you need to first set GraphLinksModel.linkKeyProperty.

I am using Electron and NodeJS

For explanation purpose:
I do have an Electron App, which hosts an http Server via NodeJS locally. The Website containing the Diagram asks every 3s for an data update and replaces the old data with the changed on. The data can be changed using the Electron app.
The data-array contains an object-array (NodeData and LinkData), which is used for setting up the Diagram.
The Diagram shows an relation tree between teams in a contest.
Data is changed via the Electron App: e.g. a team won and comes to the next round.
To show that, I’d like to update the Diagram without reloading the page.

Yes, call those two merge… methods, as I showed.

outside the render() function?

Rendering means setting up the HTMLDivElement and creating the Diagram and initializing it with various properties and templates and maybe setting up some tools. This is all stuff that need only be done once for the life of the diagram.

But each time you want to update the model data, there are two ways to go. The traditional way is that you have to call a Model method to change the state, and you make all of the changes within a single transaction. This will automatically update the diagram.

The other way is if you have no control over the code that is modifying the data, so you cannot make that code call a Model method in order to modify the state. Now there are two possibilities: that external code is modifying the model state directly, or it is modifying a copy of the data. I’ll assume your situation is the latter, and that the external code never modifies the key of any node or link. In that case when you want the diagram to update you call the code that I wrote above, with calls to merge…. As always, those calls also have to be performed within a transaction.

This is all covered by GoJS Using Models -- Northwoods Software

Does the merge also work when new nodes with new links are added?

Yes, and when nodes or links are removed.

So that question implies that the other code is working on a copy of the data. Is that correct? If so, then the next question is whether changes are made only by copying – i.e. treating data as immutable. This is mostly just a design and implementation issue for you – it doesn’t really change how your GoJS-related code should be implemented, since it has always been designed for and operated on mutable data.

Yes the Code works with a copy of the data; it has the same structure…
The Diagram is directly built at the page call with the data_array from the server. Afterwards this data_array gets replaced constantly every data-update.

I implemented your model.commit code and tried it.
The addition and removal of nodes worked for the first time.
But the links weren’t added or removed - I got an error telling me that I would work with an empty string, which isn’t the case.

This caused for some more in depth research of your GoJs API.

I found as you had mentioned earlier a way to update the whole model.
Update All Relationships From Data

But I hadn’t found any way to call it without throwing an error.
Would this method: “updateAllRelationshipsFromData()” also work in my case?

And at last I would like to ask how I can reorient the Diagram to the Div after modifying it.
After the addition and removal of nodes worked the first time, I noticed, that only the nodes disappeared and the diagram hadn’t oriented itself back to the middle of the frame.
Following function hadn’t worked: myDiagram.commandHandler.zoomToFit()

May you can help me there also?

Every time you construct a GraphLinksModel, you need to set its properties before setting its data arrays or calling Model.toJson.

Calling updateAllRelationshipsFromData could work if it had been the existing objects in the model that had been modified. And if you don’t need to undo.

Does calling myDiagram.zoomToFit() work? Or setting Diagram.autoScale?

zoomToFit only works after creating the Diagram with render()
But calling it after the nodes are added or removed doesn’t work

I had a spontaneous idea which had worked - I don’t know why

function update(){
   myDiagram.model = new go.GraphLinksModel(node_data, link_data);
   myDiagram.commandHandler.zoomToFit();
}

It adds and removes nodes and links and it is zoomed to fit

I would like to hear an explanation to that.
And I also want to thank you walter for your helpful support

This is what I suggested in my first reply if you expect there to be little in common between the old diagram and the new diagram. Just load a new diagram. But that is expensive because it discards all of the existing nodes and links and creates new ones from the new data.

From your recent description it sounds as if the model is only changing slightly and frequently. In that case you should do what I suggested in my first reply by calling the merge… model methods.

Furthermore I will guess that you don’t want to undo those changes, so you don’t want to record those changes in the UndoManager. You can do that by temporarily setting skipsUndoManager to true, or by passing null as the second argument to commit.

So I think you actually want to do:

myDiagram.model.commit(m => {
  m.mergeNodeDataArray(newNodeDataArray);
  m.mergeLinkDataArray(newLinkDataArray);
}, null);
myDiagram.commandHandler.zoomToFit();