Using gojs in node to render large layouts on the server side

I have a case where I need to render very large layouts, which take up a lot of time. So as an optimisation technique, I thought of using the server to render those layouts, calculating the location of and all the other required info for each node, and just send that data to the front-end for rendering. So I followed this guide. The documentation clearly mentions that “it will output Model JSON results in the console, which include the locations of laid-out Nodes”, however that is not working for me as this Model JSON does not contain the location of laid-out nodes, but rather just preliminary information like “nodeDataArray” and “linkDataArray”. So needless to say, my rendering is still taking similar amount of time.

My front-end is based on react.

I would really appreciate your support.

Do your node templates have TwoWay Bindings on the Node.location property so that the model data has the location information on each node data object?

Hi Walter,
Thanks for your response. To answer your question, I have not added the TwoWay binding in my templates yet, but that is not relevant for the backend. My backend is supposed to calculate the locations for the nodes and send that data for the front-end to process, which is where the templates are defined, and where the TwoWay binding is supposed to read the location of each node. My issue is that the data that is being sent from the backend has no “location” property it in, but the documentation (GoJS in Node.js -- Northwoods Software) suggests that there should be a location property for every node.

That is the purpose of the TwoWay Bindings – to save changes of Node or Link properties (in this case Node.location, set by the layout) to the corresponding node or link data objects in the model.

Yes, that makes sense. However, I still don’t see how that would solve my problem. The issue is that I am rendering a very large layout based on nodes data fetched from an api call. So since the calculations for arranging those nodes on the 2-D canvas takes place on the front-end, it causes a very large delay or lag. My idea was that if we could simply perform these calculations on the backend, so that the front-end received data about the nodes, as well as where to place these nodes on the 2-D canvas (from the location property of nodes that the backend is supposed to calculate), then my front-end won’t have to perform all those calculations, which would rid us of all the lagging.
The documentation that I referred to, did suggest that this approach is possible, and that following that tutorial, I would be getting automatically calculated locations of my nodes in the myDiagram.model.nodeDataArray property.
My issue is that this is not happening. The individual node objects in the myDiagram.model.nodeDataArray array simply do not contain the location property.

Do all of your node templates include this binding?

    new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify)

The name of the data property, “loc” in this example, doesn’t really matter – it’s where the model will have that location information.

I assume you are doing your layouts when it is convenient and then saving the model so that whenever any user requests the model it will have the location information available on the node data objects.

When that location information is available, you will want to set Layout.isInitial to false on your Diagram.layout (and on any Group.layouts, if you are using Groups too). You can do that before setting Diagram.model. Although if you can be sure that every model will have location information on every node data object, then I suppose you could just set Layout.isInitial to false when you initialize the diagram, rather than checking before setting Diagram.model.

Yes, that is exactly what I am doing. But I don’t want to manually set “loc” property for each node, as that would not be possible. According to the documentation, I should be getting locations of laid out nodes if I do rendering on the the backend as suggested. The quote below is excerpted from gojs official documentation:

“If you saved the following JavaScript as nodescript.js and run it with node (node nodescript.js ), it will output Model JSON results in the console, which include the locations of laid-out Nodes.”

As you can see, the output should contain nodes with their locations figured out, but that is not happening. The data that I get is like :
“key”: “order-payment-engine-health.controller.ts-305-0”,
“category”: “gridLayout”,
“isSubGraphExpanded”: true,
“isGroup”: true,
“group”: “order-payment-engine”,
“text”: “health.controller.ts”,
“kind”: 305,
“kindName”: “SourceFile”,
“fileName”: “health.controller.ts”,
“appName”: “order-payment-engine”,
“color”: “lightcyan”

I expect a “loc” or “location” property in here as well that I can extract in my template by using the TwoWay binding as you mentioned above.
I would really appreciate it if you could tell me how to achieve that which is defined in the documentation that I am referencing to => GoJS in Node.js -- Northwoods Software

Yes, that’s exactly the purpose of that example at GoJS in Node.js -- Northwoods Software
Note how all of the node templates (in that case there is just one) have a TwoWay Binding on the Node.location property.

It appears that you are also using Groups. Does that template also have such a Binding?

Ahhhh yes, that must be it. I have different nodes, with groups being the most common, and the documentation that I was referring to did not define a group template, which is why my end nodes did not have a location property.
Thanks a lot Walter, I really appreciate your help!!