Events
AlpineFlow emits events for every significant interaction, structural change, and lifecycle transition. Events can be consumed in three ways.
Click nodes, drag them, create connections — the devtools panel logs every event:
<div x-data="flowCanvas({
nodes: [
{ id: 'a', position: { x: 0, y: 0 }, data: { label: 'Click me' } },
{ id: 'b', position: { x: 250, y: 0 }, data: { label: 'Drag me' } },
],
edges: [],
background: 'dots',
fitViewOnInit: true,
controls: false,
pannable: false,
zoomable: false,
debug: true,
})" class="flow-container" style="height: 250px;">
<div x-flow-devtools></div>
<div x-flow-viewport>
<template x-for="node in nodes" :key="node.id">
<div x-flow-node="node">
<div x-flow-handle:target></div>
<span x-text="node.data.label"></span>
<div x-flow-handle:source></div>
</div>
</template>
</div>
</div>
Listening to Events
1. Config Callbacks
Pass callback functions in the flowCanvas() configuration. The callback name follows the pattern on + PascalCase event name.
<div x-data="flowCanvas({
nodes: [...],
onNodeClick: (detail) => console.log('Clicked:', detail.node.id),
onConnect: (detail) => console.log('Connected:', detail.connection),
})">
2. Alpine Event Directives
Events are dispatched as DOM CustomEvents on the container with a flow- prefix. Use Alpine's @ directive to listen.
<div x-data="flowCanvas({ nodes: [...] })"
@flow-node-click="console.log('Clicked:', $event.detail.node.id)"
@flow-connect.window="handleConnect($event.detail)">
Events bubble, so you can also listen on parent elements or window.
3. Direct DOM Listeners
For vanilla JavaScript integration:
document.querySelector('[data-flow-canvas]')
.addEventListener('flow-node-click', (e) => {
console.log('Clicked:', e.detail.node.id);
});
Node Interaction Events
node-click
Fired when a node is clicked.
{ node: FlowNode; event: MouseEvent }
Config callback: onNodeClick
node-drag-start
Fired when a node drag operation begins.
{ node: FlowNode }
Config callback: onNodeDragStart
node-drag
Fired continuously during a node drag.
{ node: FlowNode; position: XYPosition }
Config callback: onNodeDrag
node-drag-end
Fired when a node drag operation ends.
{ node: FlowNode; position: XYPosition }
Config callback: onNodeDragEnd
node-resize-start
Fired when a node resize begins (via x-flow-resizer).
{ node: FlowNode; dimensions: Dimensions }
Config callback: onNodeResizeStart
node-resize
Fired continuously during a node resize.
{ node: FlowNode; dimensions: Dimensions }
Config callback: onNodeResize
node-resize-end
Fired when a node resize ends.
{ node: FlowNode; dimensions: Dimensions }
Config callback: onNodeResizeEnd
node-context-menu
Fired when a node is right-clicked.
{ node: FlowNode; event: MouseEvent }
Config callback: onNodeContextMenu
node-collapse
Fired when a node is collapsed (descendants hidden).
{ node: FlowNode; descendants: string[] }
Config callback: onNodeCollapse
node-expand
Fired when a node is expanded (descendants restored).
{ node: FlowNode; descendants: string[] }
Config callback: onNodeExpand
node-condense
Fired when a node switches to condensed (summary) view.
{ node: FlowNode }
Config callback: onNodeCondense
node-uncondense
Fired when a node restores full row view.
{ node: FlowNode }
Config callback: onNodeUncondense
Edge Interaction Events
edge-click
Fired when an edge is clicked.
{ edge: FlowEdge; event: MouseEvent }
Config callback: onEdgeClick
edge-context-menu
Fired when an edge is right-clicked.
{ edge: FlowEdge; event: MouseEvent }
Config callback: onEdgeContextMenu
Connection Events
connect-start
Fired when a connection drag begins from a source handle.
{ source: string; sourceHandle?: string }
Config callback: onConnectStart
connect
Fired when a connection is successfully created (single connection).
{ connection: Connection }
Where Connection is { source: string; sourceHandle?: string; target: string; targetHandle?: string }.
Config callback: onConnect
multi-connect
Fired when multiple connections are created in a single multi-connect drag.
{ connections: Connection[] }
Config callback: onMultiConnect
connect-end
Fired when a connection drag ends (whether successful or cancelled).
{
connection: Connection | null;
source: string;
sourceHandle?: string;
position: XYPosition;
}
connection is null if the drag was cancelled without creating an edge.
Config callback: onConnectEnd
Reconnection Events
reconnect-start
Fired when an edge endpoint reconnection drag begins.
{ edge: FlowEdge; handleType: HandleType }
Where HandleType is 'source' | 'target'.
Config callback: onReconnectStart
reconnect
Fired when an edge is successfully reconnected to a new handle.
{ oldEdge: FlowEdge; newConnection: Connection }
Config callback: onReconnect
reconnect-end
Fired when an edge reconnection drag ends.
{ edge: FlowEdge; successful: boolean }
Config callback: onReconnectEnd
Viewport Events
viewport-change
Fired whenever the viewport state changes (any pan or zoom).
{ viewport: Viewport }
Config callback: onViewportChange
viewport-move-start
Fired when a user gesture (pan/zoom) starts.
{ viewport: Viewport }
Config callback: onViewportMoveStart
viewport-move
Fired each frame during a user gesture (pan/zoom).
{ viewport: Viewport }
Config callback: onViewportMove
viewport-move-end
Fired when a user gesture (pan/zoom) ends.
{ viewport: Viewport }
Config callback: onViewportMoveEnd
Canvas Events
pane-click
Fired when the canvas background (empty space) is clicked.
{ event: MouseEvent; position: XYPosition }
position is in flow coordinates.
Config callback: onPaneClick
pane-context-menu
Fired when the canvas background is right-clicked.
{ event: MouseEvent; position: XYPosition }
Config callback: onPaneContextMenu
Selection Events
selection-change
Fired whenever the set of selected nodes, edges, or rows changes.
{
nodes: string[]; // selected node IDs
edges: string[]; // selected edge IDs
rows: string[]; // selected row IDs
}
Config callback: onSelectionChange
selection-context-menu
Fired when right-clicking with multiple nodes selected.
{ nodes: FlowNode[]; event: MouseEvent }
Config callback: onSelectionContextMenu
Structure Events
nodes-change
Fired when nodes are added or removed.
{ type: 'add' | 'remove'; nodes: FlowNode[] }
Config callback: onNodesChange
edges-change
Fired when edges are added or removed.
{ type: 'add' | 'remove'; edges: FlowEdge[] }
Config callback: onEdgesChange
nodes-patch
Fired when nodes are patched (partial updates).
{ patches: Record<string, DeepPartial<FlowNode>> }
Config callback: onNodesPatch
edges-patch
Fired when edges are patched (partial updates).
{ patches: Record<string, DeepPartial<FlowEdge>> }
Config callback: onEdgesPatch
node-filter-change
Fired when a node-level filter is applied or cleared.
{ filtered: FlowNode[]; visible: FlowNode[] }
Row Events
row-select
Fired when a row is selected.
{ rowId: string; nodeId: string; attrId: string }
row-deselect
Fired when a row is deselected.
{ rowId: string; nodeId: string; attrId: string }
row-selection-change
Fired whenever the set of selected rows changes.
{ selectedRows: string[] }
Lifecycle Events
init
Fired after the canvas is fully initialized.
undefined
Config callback: onInit
destroy
Fired when the canvas is being destroyed (cleanup).
undefined
Config callback: onDestroy
Additional Events
These events are emitted internally but do not have dedicated config callbacks. Listen via DOM event directives.
| Event | Payload | When |
|---|---|---|
save |
{ nodes, edges, viewport } |
toObject() is called |
restore |
{ nodes?, edges?, viewport? } |
fromObject() is called |
copy |
{ nodeCount, edgeCount } |
Clipboard copy |
paste |
{ nodes, edges } |
Clipboard paste |
cut |
{ nodeCount, edgeCount } |
Clipboard cut |
layout |
{ type, direction?, ... } |
Layout algorithm applied |
compute-complete |
{ results: Map } |
Compute engine finishes |
node-reparent |
{ node, oldParentId, newParentId } |
Node reparented |
child-reorder |
{ nodeId, parentId, order } |
Child reordered in layout parent |
panel-reset |
undefined |
resetPanels() called |
helper-lines-change |
{ horizontal: number[], vertical: number[] } |
Alignment guides update during drag |
Quick Reference
All events at a glance:
| Event | Payload | Config Callback |
|---|---|---|
node-click |
{ node, event } |
onNodeClick |
node-drag-start |
{ node } |
onNodeDragStart |
node-drag |
{ node, position } |
onNodeDrag |
node-drag-end |
{ node, position } |
onNodeDragEnd |
node-resize-start |
{ node, dimensions } |
onNodeResizeStart |
node-resize |
{ node, dimensions } |
onNodeResize |
node-resize-end |
{ node, dimensions } |
onNodeResizeEnd |
node-context-menu |
{ node, event } |
onNodeContextMenu |
node-collapse |
{ node, descendants } |
onNodeCollapse |
node-expand |
{ node, descendants } |
onNodeExpand |
node-condense |
{ node } |
onNodeCondense |
node-uncondense |
{ node } |
onNodeUncondense |
edge-click |
{ edge, event } |
onEdgeClick |
edge-context-menu |
{ edge, event } |
onEdgeContextMenu |
connect-start |
{ source, sourceHandle? } |
onConnectStart |
connect |
{ connection } |
onConnect |
multi-connect |
{ connections } |
onMultiConnect |
connect-end |
{ connection?, source, sourceHandle?, position } |
onConnectEnd |
reconnect-start |
{ edge, handleType } |
onReconnectStart |
reconnect |
{ oldEdge, newConnection } |
onReconnect |
reconnect-end |
{ edge, successful } |
onReconnectEnd |
viewport-change |
{ viewport } |
onViewportChange |
viewport-move-start |
{ viewport } |
onViewportMoveStart |
viewport-move |
{ viewport } |
onViewportMove |
viewport-move-end |
{ viewport } |
onViewportMoveEnd |
pane-click |
{ event, position } |
onPaneClick |
pane-context-menu |
{ event, position } |
onPaneContextMenu |
selection-change |
{ nodes, edges, rows } |
onSelectionChange |
selection-context-menu |
{ nodes, event } |
onSelectionContextMenu |
nodes-change |
{ type, nodes } |
onNodesChange |
edges-change |
{ type, edges } |
onEdgesChange |
nodes-patch |
{ patches } |
onNodesPatch |
edges-patch |
{ patches } |
onEdgesPatch |
node-filter-change |
{ filtered, visible } |
— |
row-select |
{ rowId, nodeId, attrId } |
— |
row-deselect |
{ rowId, nodeId, attrId } |
— |
row-selection-change |
{ selectedRows } |
— |
init |
— | onInit |
destroy |
— | onDestroy |
save |
{ nodes, edges, viewport } |
— |
restore |
{ nodes?, edges?, viewport? } |
— |
copy |
{ nodeCount, edgeCount } |
— |
paste |
{ nodes, edges } |
— |
cut |
{ nodeCount, edgeCount } |
— |
layout |
{ type, direction?, ... } |
— |
compute-complete |
{ results: Map } |
— |
node-reparent |
{ node, oldParentId, newParentId } |
— |
child-reorder |
{ nodeId, parentId, order } |
— |
panel-reset |
— | — |
helper-lines-change |
{ horizontal, vertical } |
— |
See Also
- Configuration > Event Callbacks -- Configuring callbacks
- $flow Magic -- Programmatic API