/Connectors are real elements rendered by custom nodes. They identify edge endpoints, provide path direction and can carry custom content, constraints and application data.
df-inputAccepts regular draggable connections.df-outputStarts a regular connection by default. Both connector types require [connectorData] with a node id, connector id and single constraint. When single is true, a connected input rejects another edge and a connected output cannot start another edge or action.
{nodeId}-input-1 and {nodeId}-output-1 . Place connectors with the custom node's CSS. The position input accepts Top , Right , Bottom or Left and tells Bezier or SmoothStep calculation which direction the path should leave or approach. It does not move the connector element.
The [content] input accepts any Polymorpheus content: text, a component or an ng-template . A template receives the complete DfDataConnectorConfig as its implicit context, including optional application data .
task-node.component.html
<ng-template
#connectorContent
let-connector
>
<tui-icon icon="@tui.plus" />
<span>{{ connector.data?.['label'] }}</span>
</ng-template>
<df-output
[connectorData]="{
nodeId: nodeIdSignal(),
connectorId: nodeIdSignal() + '-output-1',
single: false,
data: {label: 'Add child'},
}"
[content]="connectorContent"
/>
DfOutputMode.Connection is the default output mode. A pointer drag starts a draft edge and dropping it on an input appends a connection to the bound model. Regular outputs do not emit application actions.
Set DfOutputMode.Action when a click should request an application-owned graph mutation. The output remains visible when regular connection creation is disabled, never starts a draft edge and emits its connector config through (activated) .
tree-node.component.html
<ng-template #addChildIcon>
<tui-icon icon="@tui.plus" />
</ng-template>
<df-output
title="Add child"
[connectorData]="{
nodeId: nodeIdSignal(),
connectorId: nodeIdSignal() + '-add-child',
single: false,
data: {childType: 'task'},
}"
[content]="addChildIcon"
[layoutOrder]="0"
[mode]="outputMode.Action"
(activated)="addChild($event)"
/>
The connector does not add a node itself. The handler creates both the child and its edge, then passes the complete next model to the layouts service.
dynamic-tree.component.ts
private readonly autoLayout = inject(DfAutoLayoutService);
readonly outputMode = DfOutputMode;
addChild({nodeId, connectorId}: DfDataConnectorConfig): void {
const model = this.form.getRawValue();
const parent = model.nodes.find(({id}) => id === nodeId);
if (!parent) {
return;
}
const childId = crypto.randomUUID();
const position = 'position' in parent ? {...parent.position} : {x: 0, y: 0};
this.autoLayout.apply({
anchorNodeId: nodeId,
model: {
nodes: [
...model.nodes,
{
id: childId,
data: {type: 'task', title: 'New task'},
position,
},
],
connections: [
...model.connections,
{
source: {
nodeId,
connectorId,
connectorType: DfConnectionPoint.Output,
},
target: {
nodeId: childId,
connectorId: `${childId}-input-1`,
connectorType: DfConnectionPoint.Input,
},
},
],
},
});
}
Multiple action outputs can carry different data or constraints. In strict-tree layouts, assign connected outputs a unique zero-based layoutOrder in visual order: top to bottom for horizontal trees and left to right for vertical trees.
Override --df-connector-input-color , --df-connector-output-color and their -hover variants on ng-draw-flow . The generic --df-connector-color remains a fallback for both types.
Continue with connection rendering or the dynamic layouts guide .