Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:FlowiseAI Flowise OnConnect

From Leeroopedia
Attribute Value
Source Repository FlowiseAI/Flowise
Source File packages/ui/src/views/canvas/index.jsx
Domain Chatflow_Creation
Workflow Chatflow_Creation
Last Updated 2026-02-12

Overview

Concrete ReactFlow event handler for creating validated edges between canvas nodes. The onConnect handler in the Canvas component receives a connection object from ReactFlow, constructs a typed edge, updates the target node's input data with a reference to the source node, and adds the edge to the ReactFlow edges state. Connection validation is handled by a separate isValidConnection callback.

Code Reference

Source Location

  • File: packages/ui/src/views/canvas/index.jsx
  • Lines: L119-164 (onConnect handler)
  • Lines: L414-449 of packages/ui/src/utils/genericHelper.js (isValidConnection)

Signature

const onConnect = (params) => {
    const newEdge = {
        ...params,
        type: 'buttonedge',
        id: `${params.source}-${params.sourceHandle}-${params.target}-${params.targetHandle}`
    }
    // ... update target node inputs and add edge
}

The connection validation function:

export const isValidConnection = (connection, reactFlowInstance) => {
    const sourceHandle = connection.sourceHandle
    const targetHandle = connection.targetHandle
    const target = connection.target

    let sourceTypes = sourceHandle.split('-')[sourceHandle.split('-').length - 1].split('|')
    let targetTypes = targetHandle.split('-')[targetHandle.split('-').length - 1].split('|')

    if (targetTypes.some((t) => sourceTypes.includes(t))) {
        // Check single-input constraint and list anchor rules
        // ...
        return true
    }
    return false
}

Import

// onConnect is defined inline in the Canvas component
// isValidConnection is imported from genericHelper:
import { isValidConnection } from '@/utils/genericHelper'

// addEdge is from ReactFlow:
import { addEdge } from 'reactflow'

I/O Contract

Inputs

Parameter Type Required Description
params object Yes ReactFlow connection object
params.source string Yes Source node ID
params.sourceHandle string Yes Source handle ID (encodes output name and base classes)
params.target string Yes Target node ID
params.targetHandle string Yes Target handle ID (encodes input name and accepted types)

Outputs

Output Type Description
(side effect) Edge added A new edge is added to the ReactFlow edges state with type "buttonedge"
(side effect) Node input updated The target node's data.inputs[targetInput] is updated with a reference to the source node
(side effect) Dirty flag set The canvas is marked as dirty (unsaved changes)

Implementation Details

Edge Construction

Each new edge receives a deterministic ID composed from the connection parameters:

const newEdge = {
    ...params,
    type: 'buttonedge',
    id: `${params.source}-${params.sourceHandle}-${params.target}-${params.targetHandle}`
}

The type: 'buttonedge' tells ReactFlow to render this edge using the custom ButtonEdge component, which includes a delete button on the edge.

Target Node Input Update

The handler extracts the target input name from the target handle ID and updates the node's inputs:

const targetNodeId = params.targetHandle.split('-')[0]
const sourceNodeId = params.sourceHandle.split('-')[0]
const targetInput = params.targetHandle.split('-')[2]

setNodes((nds) =>
    nds.map((node) => {
        if (node.id === targetNodeId) {
            let value
            const inputAnchor = node.data.inputAnchors.find((ancr) => ancr.name === targetInput)
            const inputParam = node.data.inputParams.find((param) => param.name === targetInput)

            if (inputAnchor && inputAnchor.list) {
                // List anchor: append to array
                const newValues = node.data.inputs[targetInput] || []
                if (targetInput === 'tools') {
                    rearrangeToolsOrdering(newValues, sourceNodeId)
                } else {
                    newValues.push(`{{${sourceNodeId}.data.instance}}`)
                }
                value = newValues
            } else if (inputParam && inputParam.acceptVariable) {
                // Variable-accepting param: keep existing value
                value = node.data.inputs[targetInput] || ''
            } else {
                // Single anchor: set to source reference
                value = `{{${sourceNodeId}.data.instance}}`
            }

            node.data = {
                ...node.data,
                inputs: { ...node.data.inputs, [targetInput]: value }
            }
        }
        return node
    })
)

Connection Validation (isValidConnection)

The validation function extracts type arrays from handle IDs and checks for type intersection:

// Handle ID format: "nodeId-output-name-TypeA|TypeB"
let sourceTypes = sourceHandle.split('-').pop().split('|').map(s => s.trim())
let targetTypes = targetHandle.split('-').pop().split('|').map(t => t.trim())

// Valid if any source type matches any target type
if (targetTypes.some((t) => sourceTypes.includes(t))) {
    // Additional checks: single-input constraint, list anchors
    let targetNode = reactFlowInstance.getNode(target)
    const targetNodeInputAnchor = targetNode.data.inputAnchors.find((ancr) => ancr.id === targetHandle)

    if ((targetNodeInputAnchor && !targetNodeInputAnchor.list &&
         !reactFlowInstance.getEdges().find((e) => e.targetHandle === targetHandle))
        || targetNodeInputAnchor?.list) {
        return true
    }
}
return false

Usage Examples

How onConnect is wired to ReactFlow

import ReactFlow, { addEdge } from 'reactflow'
import { isValidConnection } from '@/utils/genericHelper'

const Canvas = () => {
    const [edges, setEdges] = useEdgesState()
    const { reactFlowInstance } = useContext(flowContext)

    const onConnect = (params) => {
        const newEdge = {
            ...params,
            type: 'buttonedge',
            id: `${params.source}-${params.sourceHandle}-${params.target}-${params.targetHandle}`
        }
        // Update target node inputs...
        setEdges((eds) => addEdge(newEdge, eds))
    }

    return (
        <ReactFlow
            edges={edges}
            onConnect={onConnect}
            isValidConnection={(connection) =>
                isValidConnection(connection, reactFlowInstance)
            }
        />
    )
}

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment