Dragging a Node with Its Children in React Flow

77 Views Asked by At

I am working with React Flow and I am trying to achieve a behavior where dragging a node also moves all the nodes connected to it as children. Does anyone know of a solution that would allow for this?

I've attempted a solution as shown below, but it doesn't fully work as expected. The connected nodes do move with the dragged node, however, the movement does not account for the zoom level.

Here's the code snippet I tried:

function onNodesDrag(event: React.MouseEvent, node: Node) {
       const { movementX, movementY } = event;

       const nodes = getNodes();
       const edges = getEdges();

       const dx = movementX;
       const dy = movementY;

       const connectedEdges = edges.filter((edge) => edge.source === node.id);

       const connectedNodeIds = new Set(
         connectedEdges.map((edge) =>
           edge.source === node.id ? edge.target : edge.source
         )
       );

       const updatedNodes = nodes.map((n) => {
         if (n.id === node.id || connectedNodeIds.has(n.id)) {
           return {
             ...n,
             position: {
               x: n.position.x + dx,
               y: n.position.y + dy,
             },
           };
         }
         return n;
       });

       setNodes(updatedNodes);
     }

I also tried a version where I fetched the zoom value from React Flow, but the calculations I performed were incorrect. Can someone guide me on how to properly account for the zoom level when moving nodes and their connected children?

1

There are 1 best solutions below

0
Pyot On

To solve this problem, you need to utilize a Sub Flow where the child nodes are configured to point to a parentNode, and the extent should be explicitly defined. Unfortunately, the documentation primarily showcases examples with extent: 'parent', which may give the impression that nodes can only be moved within their parentNode.

To understand how it functions, check out this example: https://codesandbox.io/p/sandbox/hopeful-sun-hx2gw7?file=%2Fnodes.js&utm_medium=sandpack

Modify nodes.js as follows:

const nodes = [
  {
    id: "A",
    type: "",
    data: { label: null },
    position: { x: 0, y: 0 },
    style: {
      width: 170,
      height: 140,
    },
  },
  {
    id: "B",
    type: "input",
    data: { label: "child node 1" },
    position: { x: 10, y: 10 },
    parentNode: "A",
  },
  {
    id: "C",
    data: { label: "child node 2" },
    position: { x: 10, y: 90 },
    parentNode: "A",
  },
];

export default nodes;

After making these changes, when you move the parent node, the child nodes will follow the parent node accordingly.