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 };
});
});
}
},
[]);
Resize Group
As of v11.3, Resizing node is possible and reactflow(previously react-flow-renderer)
library has a component for that.
So after pondering upon the issue so many times, I realized, I was actually getting position of mousePointer
instead of actual node. I had 2 scenarios to deal with.
Outside to inside Group
nodeWithUpdatedPosition.position = {
x: draggedNode.positionAbsolute?.x! - targetGroupNode.position.x,
y: draggedNode.positionAbsolute?.y! - targetGroupNode.position.y,
};
You have to subtract position of targetGroupNode
because if you add parent to any node, its position will be relative to that group(targetGroupNode) meaning if you give draggedNode
position of {x:0, y:0}
then it will be placed at top-left corner inside targetGroupNode
. Subtracting from positionAbsolute
will make the position relative to groupNode
.
Inside to Outside Group
nodeWithUpdatedPosition.position = draggedNode.positionAbsolute!
This resolved all of the issues related to positioning of nodes. It works even if user drag, zoom in or zoom out the canvas.