How to manually layout of specific node in TreeLayout?

  1. I need to move the node to save the location of the node, but not the children.
  2. Automatic layout when child nodes moved.

Any examples here?

Thanks!

Normally one overrides some methods of TreeLayout, such as:
https://gojs.net/latest/api/symbols/TreeLayout.html#assignTreeVertexValues, before any vertex is positioned
https://gojs.net/latest/api/symbols/TreeLayout.html#commitNodes, after all vertexes have been positioned

If you do not want a subtree to be moved when the user drags a node, do not set https://gojs.net/latest/api/symbols/DraggingTool.html#dragsTree to true.

Almost always if you explicitly perform a layout after the user has moved one or more nodes, those nodes will be moved to where the layout thinks they belong, thereby losing the movement that the user just did. Could you please be more specific about what you want to accomplish?

Like this

Child node can be adjust the order, Root node can be move anywhere.

OK, so you want to set DraggingTool.dragsTree to true, and you want to set TreeLayout.arrangement to go.TreeLayout.ArrangementFixedRoots.

Keeping the sort order of siblings based on the Y location of each child can be done by setting TreeLayout.comparer to a function that compares the child vertexes by their vertex.node.location.y values. I can’t create this for you now, but maybe tomorrow if I have some free time. It ought to look something like:

  $(go.TreeLayout,
    { . . .,
      arrangement: go.TreeLayout.ArrangementFixedRoots,
      comparer: function(a, b) {
        var ay = a.node ? a.node.location.y : 0;
        var by = b.node ? b.node.location.y : 0;
        if (isNaN(ay) || isNaN(by)) return 0;
        if (ay < by) return -1;
        if (ay > by) return 1;
        return 0;
      };
    })

Thank you very much!

@walter Hi, Does have any progress?

Did what I provide above not help you? If not, why not?

I thought …

When I answered I tried to help you immediately by providing that code in my response, rather than waiting until I had time for a complete sample.

output
@walter

If you drag the C node to any position above B, the positions of B and C should be swapped.

Is it necessary to save a position field and update the position value after dragging and releasing the mouse? But I passed model.setDataProperty without any effect.

 layout: graph(TreeLayout, {
    // sorting: TreeLayout.SortingAscending,
    arrangement: TreeLayout.ArrangementFixedRoots,
    comparer: (prev, next) => {
      if (prev.node.data.position > next.node.data.position) {
        return -1
      } else {
        return 0
      }
    }
  }),
  'SelectionMoved': () => {
    this.diagram.selection.each(n => n.invalidateLayout())
  }

Is data.position a number? If not, the comparison will fail or not be reliable.

The comparer does not have to work on model data. The code I gave you above only depends on the Node.location.

Is there no way to achieve drag-child sorting?

This works for me:

        $(go.Diagram, . . .,
          { . . .,
            "draggingTool.dragsTree": true,
            layout:
              $(go.TreeLayout,
                { . . .,
                  arrangement: go.TreeLayout.ArrangementFixedRoots,
                  sorting: go.TreeLayout.SortingAscending,
                  comparer: function(a, b) {
                    var ay = a.node ? a.node.location.y : 0;
                    var by = b.node ? b.node.location.y : 0;
                    if (isNaN(ay) || isNaN(by)) return 0;
                    if (ay < by) return -1;
                    if (ay > by) return 1;
                    return 0;
                  }
                }),
            "SelectionMoved": function(e) { e.diagram.layout.invalidateLayout(); }
          })

Thanks, How to save?

Don’t you have a TwoWay Binding on the Node.location property?

If I move the parent node, will the positions of all child nodes be persisted to the database?

I need to keep these order when I open it again.

If you have a TwoWay Binding on the Node location or position, yes, the model will be updated automatically upon each layout. Try it.

Thanks,
How to get the location of the selection after calling diagram.layout.invalidateLayout ()

I tried to get the latest location in SelectionMoved, but it didn’t work

Or is there any way to know which node positions have been updated after executing diagram.layout.invalidateLayout ()? The premise is that I disable the undoManager, because I have implemented the undo myself.

The selected nodes have been moved, but other nodes have been moved too, so you cannot depend on the selection collection to tell you what has moved.

If you have not enabled the UndoManager, then there will not be a record of all of the changes that have happened. Still you can get notifications of changes as ChangedEvents. You can get changes to the Diagram and GraphObjects by calling Diagram.addChangedListener to register a listener. You can get changes to the model by calling Diagram.addModelChangedListener. Please read https://gojs.net/latest/intro/changedEvents.html