-
Notifications
You must be signed in to change notification settings - Fork 1
Closed
Description
EdgeSpec missing sourceHandle / targetHandle
Description
When a node defines multiple named handles (e.g., inputs=["text", "mode"]), there is no way to route an edge to a specific handle using EdgeSpec. The sourceHandle and targetHandle fields are standard React Flow edge properties but are not exposed in the Python EdgeSpec dataclass.
Root Cause
EdgeSpec in src/panel_reactflow/base.py (line 268-304) does not include sourceHandle or targetHandle fields. The to_dict() method only serializes id, source, target, label, type, selected, data, style, and markerEnd.
Minimal Reproducible Example
import panel as pn
from panel_reactflow import ReactFlow, NodeSpec, EdgeSpec, NodeType
pn.extension("jsoneditor")
node_types = {
"producer": NodeType(type="producer", label="Producer", inputs=[], outputs=["result"]),
"consumer": NodeType(type="consumer", label="Consumer", inputs=["text", "mode"], outputs=[]),
}
flow = ReactFlow(
nodes=[
NodeSpec(id="p", type="producer", position={"x": 0, "y": 0}, label="Producer").to_dict(),
NodeSpec(id="c", type="consumer", position={"x": 400, "y": 0}, label="Consumer").to_dict(),
],
edges=[
# Want to connect producer's "result" output to consumer's "mode" input
# EdgeSpec has no sourceHandle/targetHandle fields:
EdgeSpec(id="e1", source="p", target="c").to_dict(),
# Workaround: use raw dict instead of EdgeSpec
{"id": "e2", "source": "p", "target": "c", "sourceHandle": "result", "targetHandle": "mode"},
],
node_types=node_types,
sizing_mode="stretch_both",
min_height=300,
)
flow.servable()
Expected: EdgeSpec should accept sourceHandle and targetHandle parameters.
Actual: Must bypass EdgeSpec and use a raw dict to set these fields.
Suggested Fix
Add optional fields to EdgeSpec:
@dataclass
class EdgeSpec:
# ... existing fields ...
sourceHandle: str | None = None
targetHandle: str | None = None
def to_dict(self):
payload = { ... }
if self.sourceHandle is not None:
payload["sourceHandle"] = self.sourceHandle
if self.targetHandle is not None:
payload["targetHandle"] = self.targetHandle
return payloadReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels