Resize Group type node in react-flow-renderer using mouse

Viewed 89

I want to add subflow (group type node) on button click and resize it later with mouse and add nodes inside this group with drag and drop. I have searched a lot but all I found is you have set parentNode of child to do this.

I want all this with mouse drag and drop. Is it possible with free version of React-flow-renderer ?

Edit

SandBox- > https://codesandbox.io/embed/headless-architecture-6xbzu9?fontsize=14&hidenavigation=1&theme=dark

Below I have attached onDragEnd function.. It works but when I drop a node inside group, node position changes and it goes outside group. upon moving group it moves with the group which means its parent is set correctly but position is not correct. tried to set manual position but still it is not working.

const handleDragEnd = useCallback(
(event: React.MouseEvent<Element>, node: Node) => {
  let groupNode: Node | undefined = undefined;
  if (node.type === ConstantsFlowChartNodeTypes.GROUP) return;
  nodes.map((nds: Node) => {
    if (nds.type === ConstantsFlowChartNodeTypes.GROUP) {
      console.log(
        nds.type,
        nds,
        nds.type === ConstantsFlowChartNodeTypes.GROUP
      );
      if (
        nds.position.x <= node.position.x &&
        nds.position.x + parseInt(nds.style?.width?.toString() || "0") >=
          node.position.x &&
        nds.position.y <= node.position.y &&
        nds.position.y + parseInt(nds.style?.height?.toString() || "0") >=
          node.position.y
      ) {
        groupNode = nds;
      }
    }
  });
  console.log(groupNode);
  if (groupNode) {
    const position = {
      x: event.clientX,
      y: event.clientY,
    };
    setNodes((prevNodes) => {
      return prevNodes.map((nds) => {
        nds.parentNode =
          nds.id === node.id ? groupNode?.id : nds.parentNode;
        // nds.positionAbsolute = position;
        console.log(event);
        return { ...nds };
      });
    });
  }
},
[]);
2 Answers

It's possible!

If I understand your question you need to be able to drag/drop your nodes between groups.
You can use "onDragEnd" prop in react-flow. Just pass a function to it and than whenever you drag/drop something in the canvas, it gives you the exact drop position and with some calculation, you can find the target group and update the "parentNode" of dragged node

 function handleDragEnd (event, node) {
  // node contains the absolute the drop position
 }

<ReactFlow
 ...your props
 onDragEnd={handleDragEnd}
/>

To Solve your problem of position changing when dropping Node, send reactflow instance as an argument to function. Then you can use it as shown in drag n drop example as shown below:

 const position = reactFlowInstance.project({
    x: event.clientX - reactFlowBounds.left,
    y: event.clientY - reactFlowBounds.top,
  });

This is helpful in setting the position relative to reactflow instance. or

use layout libraries like dagre or elkjs for a better tree structure. you can check the example on the below link for that Layout algorithm

Coming to point 2: The Node should stay in subflow I will suggest you use a custom node and make the node structure as follow:

{
id: '4b1',
data: { label: 'Node B.A.1' },
position: { x: 20, y: 40 },
className: 'light',
parentNode: '4b',
extent: 'parent' // this property is important to make the node stay inside parent

}

If you need further assistance feel free to share code sandbox link and I can show you there as well.

Related