Connection

API reference for the Connection class

Connection

The Connection class represents a visual link between two ports on different nodes. Connections support styling, labels, animation, and use MobX observables for reactive state management.

Constructor

Connection({
  required String id,
  required String sourceNodeId,
  required String sourcePortId,
  required String targetNodeId,
  required String targetPortId,
  bool animated = false,
  bool selected = false,
  Map<String, dynamic>? data,
  ConnectionStyle? style,
  ConnectionLabel? startLabel,
  ConnectionLabel? label,
  ConnectionLabel? endLabel,
  ConnectionEndPoint? startPoint,
  ConnectionEndPoint? endPoint,
  double? startGap,
  double? endGap,
  ConnectionEffect? animationEffect,
  List<Offset>? controlPoints,
})

Properties

Required Properties

PropertyTypeDescription
idStringUnique identifier
sourceNodeIdStringSource node ID
sourcePortIdStringSource port ID
targetNodeIdStringTarget node ID
targetPortIdStringTarget port ID

Optional Properties

PropertyTypeDefaultDescription
animatedboolfalseShow flowing animation
selectedboolfalseSelection state
dataMap<String, dynamic>?nullCustom metadata
styleConnectionStyle?nullLine style override
startLabelConnectionLabel?nullLabel at source (anchor 0.0)
labelConnectionLabel?nullLabel at center (anchor 0.5)
endLabelConnectionLabel?nullLabel at target (anchor 1.0)
startPointConnectionEndPoint?nullStart marker override
endPointConnectionEndPoint?nullEnd marker override
startGapdouble?nullGap from source port
endGapdouble?nullGap from target port
animationEffectConnectionEffect?nullAnimation effect
controlPointsList<Offset>?[]User-defined waypoints

Properties like animated, selected, and labels are MobX observables. Changes trigger automatic UI updates.

Observable Properties

The following properties are reactive and can be modified after construction:

// Get/set animation state
connection.animated = true;

// Get/set selection state
connection.selected = true;

// Get/set labels (use ConnectionLabel objects)
connection.startLabel = ConnectionLabel.start(text: 'Begin');
connection.label = ConnectionLabel.center(text: 'Data Flow');
connection.endLabel = ConnectionLabel.end(text: 'End');

// Get/set animation effect
connection.animationEffect = FlowingDashEffect();

// Get/set control points
connection.controlPoints = [Offset(300, 200), Offset(400, 200)];

ConnectionLabel

Labels are ConnectionLabel objects, not plain strings. Use the factory constructors:

// Label at start (anchor 0.0)
ConnectionLabel.start(text: 'Start', offset: 10.0)

// Label at center (anchor 0.5)
ConnectionLabel.center(text: 'Data Flow')

// Label at end (anchor 1.0)
ConnectionLabel.end(text: 'End', offset: 10.0)

// Custom anchor position
ConnectionLabel(text: 'Custom', anchor: 0.25)

labels Property

Get all non-null labels as a list:

List<ConnectionLabel> get labels

Examples

final connection = Connection(
  id: 'conn-1',
  sourceNodeId: 'node-1',
  sourcePortId: 'out-1',
  targetNodeId: 'node-2',
  targetPortId: 'in-1',
);
controller.addConnection(connection);
final connection = Connection(
  id: 'conn-2',
  sourceNodeId: 'sender',
  sourcePortId: 'output',
  targetNodeId: 'receiver',
  targetPortId: 'input',
  startLabel: ConnectionLabel.start(text: 'Send'),
  label: ConnectionLabel.center(text: 'Data Flow'),
  endLabel: ConnectionLabel.end(text: 'Receive'),
);
final connection = Connection(
  id: 'conn-3',
  sourceNodeId: 'a',
  sourcePortId: 'out',
  targetNodeId: 'b',
  targetPortId: 'in',
  style: ConnectionStyles.bezier,
  startPoint: ConnectionEndPoint.none,
  endPoint: ConnectionEndPoint.triangle,
  animated: true,
  data: {'type': 'dataflow', 'priority': 1},
);

Methods

Query Methods

involvesNode

Check if this connection involves a specific node.

bool involvesNode(String nodeId)

Example:

if (connection.involvesNode('node-a')) {
  print('Connection involves node-a');
}

involvesPort

Check if this connection involves a specific node and port combination.

bool involvesPort(String nodeId, String portId)

Effective Style Methods

Get the actual style to use, falling back to theme defaults:

// Get effective connection style
ConnectionStyle getEffectiveStyle(ConnectionStyle themeStyle)

// Get effective start endpoint
ConnectionEndPoint getEffectiveStartPoint(ConnectionEndPoint themeStartPoint)

// Get effective end endpoint
ConnectionEndPoint getEffectiveEndPoint(ConnectionEndPoint themeEndPoint)

// Get effective animation effect
ConnectionEffect? getEffectiveAnimationEffect(ConnectionEffect? themeEffect)

Example:

final style = connection.getEffectiveStyle(theme.connectionTheme.style);
final endPoint = connection.getEffectiveEndPoint(theme.connectionTheme.endPoint);

Serialization

toJson

Serialize to JSON. Labels and control points are included automatically.

Map<String, dynamic> toJson()

fromJson

Create from JSON. Labels and control points are deserialized automatically.

factory Connection.fromJson(Map<String, dynamic> json)

ConnectionStyle

Built-in connection line styles via ConnectionStyles:

StyleDescription
ConnectionStyles.straightDirect line
ConnectionStyles.bezierCurved Bezier
ConnectionStyles.stepRight-angle segments
ConnectionStyles.smoothstepSmooth orthogonal (default)

Example:

Connection(
  id: 'conn',
  sourceNodeId: 'a',
  sourcePortId: 'out',
  targetNodeId: 'b',
  targetPortId: 'in',
  style: ConnectionStyles.bezier,
)

ConnectionEndPoint

Markers at connection endpoints. Built-in options:

// No marker
ConnectionEndPoint.none

// Capsule half (default for end)
ConnectionEndPoint.capsuleHalf

// Triangle arrow
ConnectionEndPoint.triangle

// Custom marker
ConnectionEndPoint(
  shape: MarkerShapes.diamond,
  size: Size(10, 10),
  color: Colors.blue,
  borderColor: Colors.black,
  borderWidth: 1.0,
)

Animation Effects

Animate connections using ConnectionEffect subclasses:

// Flowing dashes
connection.animationEffect = FlowingDashEffect(
  speed: 2.0,
  dashLength: 10.0,
  gapLength: 5.0,
);

// Particles along path
connection.animationEffect = ParticleEffect();

// Gradient flow
connection.animationEffect = GradientFlowEffect();

// Pulsing glow
connection.animationEffect = PulseEffect();

Control Points

Add user-defined waypoints for custom routing:

// Set control points
connection.controlPoints = [
  Offset(300, 200),
  Offset(400, 200),
  Offset(400, 300),
];

// Clear control points
connection.controlPoints = [];

Control points are used by editable connection styles to let users customize connection paths.

Connection Operations

Add Connection

controller.addConnection(connection);

Remove Connection

controller.removeConnection('conn-1');

Get Connections

// All connections
final all = controller.connections;

// For a node
final nodeConns = controller.getConnectionsForNode('node-1');

Modify Labels

// Update via observable property
final conn = controller.graph.connections['conn-1'];
if (conn != null) {
  conn.label = ConnectionLabel.center(text: 'Updated Label');
}

Connection Styling

Configure appearance through ConnectionTheme:

NodeFlowTheme(
  connectionTheme: ConnectionTheme(
    style: ConnectionStyles.smoothstep,
    color: Colors.grey,
    selectedColor: Colors.blue,
    strokeWidth: 2.0,
    selectedStrokeWidth: 3.0,
    dashPattern: null, // Solid line
    startPoint: ConnectionEndPoint.none,
    endPoint: ConnectionEndPoint.capsuleHalf,
    endpointColor: Colors.grey,
    endpointBorderColor: Colors.white,
    endpointBorderWidth: 0,
    bezierCurvature: 0.5,
    cornerRadius: 4.0,
    portExtension: 20.0,
    backEdgeGap: 20.0,
    hitTolerance: 8.0,
    startGap: 0.0,
    endGap: 0.0,
  ),
)

See Connection Styles and Connection Effects for more.

Validation

Validate connections before creation using events:

events: NodeFlowEvents(
  connection: ConnectionEvents(
    onBeforeComplete: (context) {
      // Prevent self-connections
      if (context.isSelfConnection) {
        return ConnectionValidationResult.deny(
          reason: 'Cannot connect to same node',
          showMessage: true,
        );
      }

      // Ensure output-to-input direction
      if (!context.isOutputToInput) {
        return ConnectionValidationResult.deny(
          reason: 'Must connect output to input',
        );
      }

      return ConnectionValidationResult.allow();
    },
  ),
)

Best Practices

  1. Unique IDs: Use timestamps or UUIDs for connection IDs
  2. Validation: Always validate before adding connections
  3. Cleanup: Connections are auto-removed when nodes are deleted
  4. Labels: Use labels sparingly to avoid visual clutter
  5. Styling: Use consistent colors to indicate connection types
  6. Animation: Use animation effects for active data flow indication

On this page