Dragging a node outside a Group


I need to enable the user to drag a node from a group to another group.
I saw your draggble ports sample where ports are nodes in group and they can be dragged from one group to another.
I used the sample mouseDrop implementation in my group template but still when I drag a node, i cannot drag it outside the group.
What did i miss ?


Is what you want something like this sample?


Yep, this is exactly what i need.
In my current solution, when i drag a node, it resizes the group boundaries and does not leave the group.
I’m trying to understand d which code in the your sample enables the node to be dragged outside the group.
I guess it is because of computesBoundsAfterDrag set to true, right ?
But i want the two functions to work, namely to enable to user to drag a node somewhere within a group and to extend the group boundaries if requires, or drag the node outside the group (probably when holding the shift key down, or some other hot key).


Well, I first tried one way, which worked but which wasn’t a great solution. So I decided that a better way would be to customize the Placeholder’s way that it computes the area it occupies. That means overriding an undocumented method:

  function CustomPlaceholder() {
  go.Diagram.inherit(CustomPlaceholder, go.Placeholder);

  CustomPlaceholder.prototype.computeBorder = function(result) {
    var g = this.part;
    if (g instanceof go.Group) {
      var diag = g.diagram;
      var oldskip = false;
      if (diag !== null) {
        var shift = diag.lastInput.shift;
        oldskip = diag.skipsUndoManager;
        diag.skipsUndoManager = true;
        g.computesBoundsAfterDrag = shift;
      go.Placeholder.prototype.computeBorder.call(this, result);
      if (diag !== null) {
        diag.skipsUndoManager = oldskip;
    return result;

Of course you’ll now want to use this CustomPlaceholder class in your Group templates.

And if you want the default behavior that moving nodes stretches its containing group, you’ll want to turn off Group.computesBoundsAfterDrag.

Also you might find it wise to make set Layout.isRealtime to false on all of the layouts, including the Diagram.layout, though I’m not sure that is what you want.

So here is an outline of the changes in the Group template(s):

      $(go.Group, "Auto",
        { . . .,
          //computesBoundsAfterDrag: true,
          . . .,
          // Groups containing Groups lay out their members horizontally
              { isRealtime: false, . . . })
        . . .,
            { padding: 5, alignment: go.Spot.TopLeft })
      . . .


I see,
In fact i don’t use layout.
Is this code distinguish between simple node dragging and a “Shift Key hold down” node dragging ?


Yes – look at the code in CustomPlaceholder.computeBorder.


Will try out.


I tried to implement your code and the ts compiler wasn’t able to able to find the go.Placeholder.prototype.computeBorder.
Could you send a type script example ?


In TypeScript that method on Placeholder is declared as:

protected computeBorder(result: Rect): Rect;

But as I said, it’s not documented, so you will have to modify your copy of the go.d.ts file.


I searched the computeBorder in go.d.ts and didn’t find it.
From the example you sent, i understood that i need to inherit CustomPlaceHolder from go.,PlaceHolder and implement my computeBorder which overrides the PlaceHolder.computeBorder method,
but i didn’t find such method.
I’m using gojs 1.8.x


As I just said:


But the code you sent is actually calling the go.Placeholder computeBorder method :

go.Placeholder.prototype.computeBorder.call(this, result);

I have no idea what code to put in it ?


The JavaScript code that I quoted above works in the sample that I tried.

If you want to use TypeScript, then in addition to adding that declaration for Placeholder.computeBorder to the go.d.ts file, you will want to change the CustomPlaceholder definition to be a TypeScript (or at least ES6) class definition rather than the old-fashioned but compatible JavaScript code written there using .prototype. and the call to Diagram.inherit.


Works perfect,