How to position Parts correctly

I have a diagram with just 2 groups at its top level.

Here is the JSFiddle for my code: Edit fiddle - JSFiddle - Code Playground

First time the Model is loaded, I want to position the two at the opposite sides of the viewport, both at middle.

So, the “Fruits Criteria” Group (criteriaTemplate) is positioned on the left side middle, and the “Fruits Type” Group (typesTemplate) is positioned on the right side middle. Please note, the groups could be of varying heights, depending on the Model.

I have tried many things but without any success. The second group always gets placed next to where the first one is positioned.

This is how the current result looks:

And, I would like to achieve this:

How can I achieve the desired positioning?

I would appreciate any guidance.



That depends on the size of the viewport (i.e. the size of the HTML DIV element), which should vary depending on the user’s browser window and device.

The Diagram.layout is responsible for positioning the top-level nodes, which are two groups in your case. You have not set Diagram.layout, and you have not set the locations of the member nodes, so the default layout just moves the groups to be next to each other.

I think what you want to do is implement an “InitialLayoutCompleted” DiagramEvent listener. It can look at how big each group is (GraphObject.actualBounds, ignoring their positions) and how big the Diagram.viewportBounds is. Then it can call Group.move on the two groups to position them where you want them to be.

When I have time later today I can demonstrate this, if you haven’t figured it out already.

Thank you for responding, Walter!

I am still trying to solve it. I tried the approach you suggest

myDiag.addDiagramListener('InitialLayoutCompleted', function (e) {
// find output group
    const data = myDiag.model.nodeDataArray.find(aNode => aNode.category === 'output');
// find the corresponding Node
    const node = myDiag.findNodeForData(data);

I have reached to the point where I know which node needs to be modified but I am lost after that.

I was wondering if Spot could be used to somehow create the initial alignment.

An additional point: I do not mind setting a hard coded x coordinate for the ‘Output’ group, but the y will need to be determined by the relative heights of the two. The middle of the second (Output) needs to be aligned with the middle of the first (Criteria).

I look forward to your help.

Thanks again!

OK, there’s already a similar sample that always has two Groups in it: GoJS Tree Mapper

So I just added this listener to it:

        $(go.Diagram, "myDiagramDiv",
            "InitialLayoutCompleted": function(e) {
              var vb = e.diagram.viewportBounds;
              var g1 = e.diagram.findNodeForKey(-1);
              var g2 = e.diagram.findNodeForKey(-2);
              var g1b = g1.actualBounds;
              var g2b = g2.actualBounds;
              g1.moveTo(vb.x + 10, vb.y + vb.height/2 - g1b.height/2);
              g2.moveTo(vb.x + vb.width - g2b.width - 10, vb.y + vb.height/2 - g2b.height/2);
        . . .

And I think it does what you want.

Now if you want to call this code more often, for example when the sizes of the groups change or when the size of the viewport changes, then you have two choices: (1) add appropriate listeners/event handlers and call the code, or (2) define a custom Layout that has Layout.isViewportSized set to true and that overrides Layout.doLayout to do this work. Extending GoJS -- Northwoods Software

Thanks, Walter! This worked like a charm. Your additional inputs are also very helpful.