1

I use react-flow-render package. I want to add a new node between two nodes, after clicking on the label ( Edge ).

To add a new Node, it is necessary to have the sourceHandle, targetHandle , source , target

[enter image description here]

Attention: My Node can have multiple Handles

customNode.tsx

import { CSSProperties, FC, Fragment, memo, useMemo } from 'react'
import { Handle, NodeProps, Position } from 'react-flow-renderer'

interface CustomNodeProps {
    label: string
    description?: string
    target: number
    source: number
    icon: string
    style: CSSProperties | undefined
    className?: string
}

const CustomNode: FC<NodeProps<CustomNodeProps>> = ({ isConnectable, data, id, selected }) => {
    const targetHandles = useMemo(
        () =>
            !!data.target &&
            Array(data.target)
                .fill(0)
                .map((_, i) => {
                    const handleId = `target-handle-${i + 1}`
                    return (
                        <Fragment key={handleId}>
                            <Handle id={handleId} isConnectable={isConnectable} position={Position.Top} type='target' />
                        </Fragment>
                    )
                }),
        [],
    )

    const sourceHandles = useMemo(
        () =>
            !!data.source &&
            Array(data.source)
                .fill(0)
                .map((_, i) => {
                    const handleId = `source-handle-${i + 1}`
                    return (
                        <Fragment key={handleId}>
                            <Handle id={handleId} isConnectable={isConnectable} position={Position.Bottom} type='source' />
                        </Fragment>
                    )
                }),
        [],
    )

    return (
        <>
            <div>{targetHandles}</div>
            <div
                className={`react-flow__node-input ${selected ? 'selected' : ''} ${data?.className ? data.className : ''}`}
                style={data.style}
            >
                <div className='toolbar'>
                    <button className='toolbar-btn toolbar-btn-danger'>-</button>
                </div>
                {data.label}
                {data.description && <span className='react-flow__node-description'>{data.description}</span>}
            </div>
            <div>{sourceHandles}</div>
        </>
    )
}

export default memo(CustomNode)

customEdge.tsx

import { EdgeProps, getEdgeCenter, getSmoothStepPath } from 'react-flow-renderer'

const foreignObjectSize = 40

const Custom = ({
    id,
    sourceX,
    sourceY,
    targetX,
    targetY,
    sourcePosition,
    targetPosition,
    style = {},
    markerEnd,
}: EdgeProps) => {
    const edgePath = getSmoothStepPath({
        sourceX,
        sourceY,
        sourcePosition,
        targetX,
        targetY,
        targetPosition,
    })

    const [edgeCenterX, edgeCenterY] = getEdgeCenter({
        sourceX,
        sourceY,
        targetX,
        targetY,
    })

    return (
        <>
            <path id={id} style={style} className='react-flow__edge-path' d={edgePath} markerEnd={markerEnd} />
            <foreignObject
                width={foreignObjectSize}
                height={foreignObjectSize}
                x={edgeCenterX - foreignObjectSize / 2}
                y={edgeCenterY - foreignObjectSize / 2 + 10}
                requiredExtensions='http://www.w3.org/1999/xhtml'
            >
                <div className='wrapper'>
                    <button className='edge-btn edge-btn-danger'>×</button>
                    <button className='edge-btn edge-btn-success'>+</button>
                </div>
            </foreignObject>
        </>
    )
}

export default Custom
JustAG33K
  • 1,403
  • 3
  • 13
  • 28
Alikhani
  • 23
  • 6

0 Answers0