Positioning links in palette

I have created palette data as defined below. It is my understanding that links should be defined using Point. But it is unpractical because i have to take into account the other items in the palette such as nodes. In the end, links will never have the right positioning as we add more nodes in the palette (see screenshot).

So is there a way to stack automatically nodes and links in the palette ? It is working fine with nodes, but not for links obviously.

  public paletteNodeData: Array<go.ObjectData> = [
    { key: 'PaletteDecisionNode', color: 'firebrick', figure: 'Diamond', label: 'Decision' },
    { key: 'PaletteTaskNode', color: 'blueviolet', figure: 'RoundedRectangle', label: 'Task' },
    { key: 'PaletteProcessNode', color: 'yellow', figure: 'Procedure', label: 'Process' }
  ];
  public paletteLinkData: Array<go.ObjectData> = [
    { points: new go.List(/*go.Point*/).addAll([new go.Point(0, 100), new go.Point(30, 100), new go.Point(30, 140), new go.Point(60, 140)]) }
  ];

Do you want a behavior like that in https://gojs.net/latest/samples/draggableLink.html ?

I think it depends on the points in the link route being at non-negative points near the origin.

yes, this is the behavior I want, and I actually took the code from this sample. It seems the link is positioned in the palette with absolute coordinates, but it is not “stacking” automatically.

(not sure what you mean with the non-negative points)

I meant non-negative values for x and y in the Points of the Link.

But I just tried it using large values for x and y, and it still worked well:
image

can you share the code, I’m not following what you’re doing :(

I only modified the link data:

                // the Palette also has a disconnected Link, which the user can drag-and-drop
                { points: new go.List(/*go.Point*/).addAll([new go.Point(0, 0), new go.Point(30, 0), new go.Point(30, 40), new go.Point(60, 40)]) },
                { points: new go.List(/*go.Point*/).addAll([new go.Point(20, 20), new go.Point(60, 20), new go.Point(60, 40), new go.Point(60, 50)]) },
                { points: new go.List(/*go.Point*/).addAll([new go.Point(900, 900), new go.Point(930, 900), new go.Point(930, 940), new go.Point(960, 940)]) }

but that was the point I was making :) For nodes to stack up in the Palette, there’s no need for hard-coded Point coordinates.
However for Links it seems we have to hard-code coordinates. In the end it is unmanageable. Each time I will add new items to the Palette, I will have to update the coordinates of the Links.
Is there no way to make them stack automatically (similarly to the nodes) ?

I’m saying that they do stack up automatically. However, you have to provide some route for the link, otherwise there won’t be anything to show. (Since there are no connected Nodes, there’s no way for it to compute a route.) You can probably use the same route for all of your links in your palette.

I see. However I don’t experience this behavior Here I took your coordinates :

 public paletteLinkData: Array<go.ObjectData> = [

    { points: new go.List(/*go.Point*/).addAll([new go.Point(0, 0), new go.Point(30, 0), new go.Point(30, 40), new go.Point(60, 40)]) },
    { points: new go.List(/*go.Point*/).addAll([new go.Point(20, 20), new go.Point(60, 20), new go.Point(60, 40), new go.Point(60, 50)]) },
    { points: new go.List(/*go.Point*/).addAll([new go.Point(900, 900), new go.Point(930, 900), new go.Point(930, 940), new go.Point(960, 940)]) }

  ];

and this is what it looks like :
image

and then when scrolling to the bottom right :

That’s odd. I cannot explain that. If you make a copy of the Draggable Link sample, and only make the change to the link data of the palette’s model that I did, do you not get the same result that I did?

If you do, then how did you initialize your Palette?

I think it’s an issue related with conflicting css. I use bootstrap amonst others.

When the palette is loaded, the postioning is as shown in my previous screenshot. But look at what happen if I resize the browser window

It re-positions the items in the Palette ! I have no idea why.

Here’s the html. I use the angular wrapper:

<div class="row">
    <div class="col-md-2">
        <gojs-palette #myPalette [initPalette]='initPalette' [divClassName]='paletteDivClassName'
            [nodeDataArray]='paletteNodeData' [linkDataArray]='paletteLinkData' [modelData]='paletteModelData'
            (modelChange)='paletteModelChange($event)' [skipsPaletteUpdate]='skipsPaletteUpdate'></gojs-palette>
    </div>

    <div class="col-md-8">

        <gojs-diagram #myDiagram [initDiagram]='initDiagram' [nodeDataArray]='diagramNodeData'
            [linkDataArray]='diagramLinkData' [divClassName]='diagramDivClassName' [modelData]='diagramModelData'
            [skipsDiagramUpdate]='skipsDiagramUpdate' (modelChange)='diagramModelChange($event)'>
        </gojs-diagram>

    </div>
    <div class="col-md-2">

        <gojs-overview #myOverview [initOverview]='initOverview' [divClassName]='oDivClassName'
            [observedDiagram]='observedDiagram'></gojs-overview>


        <app-inspector [selectedNode]='selectedNode' (onFormChange)='handleInspectorChange($event)'>
        </app-inspector>
    </div>
</div>

and i have changed the css slightly to use 100% width:


.myPaletteDiv {
  border: 1px solid navy;
  width: 100%;
  height: 600px;
  margin: 20px;
}

hum, actually I removed all my custom css, and I removed the row and col classes. I can reproduce the problem still.

could it be that it only occurs with the Angular wrapper ?

one other problem with this approach, is that I want to have different kind of links in the palette. How would I add a link with strokes ? I tried the following with no luck:

public paletteLinkData: Array<go.ObjectData> = [

    {
      points: new go.List(/*go.Point*/).addAll([new go.Point(0, 0), new go.Point(30, 0), new go.Point(30, 40), new go.Point(60, 40)]),
      dash: [6, 3], thickness: 4
    },
    { points: new go.List(/*go.Point*/).addAll([new go.Point(20, 20), new go.Point(60, 20), new go.Point(60, 40), new go.Point(60, 50)]) },
    { points: new go.List(/*go.Point*/).addAll([new go.Point(900, 900), new go.Point(930, 900), new go.Point(930, 940), new go.Point(960, 940)]) }

  ];

The GridLayout has Layout.isViewportSized set to true, so the layout will automatically be invalidated when the window “resize” event happens. But I cannot explain why you are getting the behavior that you are. Precisely which versions of GoJS and gojs-angular are you using?

The link template is like any other template – add whatever Bindings you need.

"gojs": "^2.1.29",
 "gojs-angular": "^1.0.12",

I use Angular 11. Could that be a problem ?

Ah, yes of course, bindings :)

I have no idea if the version of Angular could be causing the problem. I would tend to doubt it.

Maybe the problem involves the timing in which the Palette is initialized and its HTMLDivElement are sized by the page. Can you find out if your code to set up the Palette and its model is being called at a time when the HTMLDivElement does not have the size it should be getting at a steady state (i.e. without any window resizing). If so, wait until the Div has the right size. Or force the layout to happen again when it does get the right size.

as you can see, when initPalette is called, the div container already has the right size :

how would I force the layout to happen again, without resizing the window ?

Been debugging step by step and I noticed that initially the shapes are positioned correctly in the palette. But at one point, the arrows move to the top. I noticed this happen here:

before this call, the shapes were correctly positioned.

Call myPalette.layoutDiagram(true)

I’ve made that call in ngAfterViewInit, but this has no effect :(