Interactive Port Features in Angular Diagram Component
29 Aug 202524 minutes to read
Ports in Angular Diagram components support various interactive features that enhance user workflow and diagram creation efficiency. This guide covers drawing connectors from ports, drag functionality, automatic port creation, tooltips, and event handling.
Draw connector from port
Ports can serve as connection points for creating connectors dynamically. Enable the Draw constraint on the constraints property to allow users to draw connectors directly from ports. The default connector segment type is Orthogonal, providing structured, right-angled connections suitable for flowcharts and organizational diagrams.
This feature is particularly useful in scenarios where users need to create connections interactively, such as building workflow diagrams or network topologies.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramModule, DiagramComponent, PointPortModel, PortVisibility,PortConstraints, PointModel, PathPortModel } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
// specifies the template string for the diagram component
template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px">
<e-nodes>
<e-node id='node1' [offsetX]=250 [offsetY]=250 [width]=100 [height]=100 [ports]='ports'></e-node>
</e-nodes>
<e-connectors>
<e-connector id='connector' type='Orthogonal' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [ports]='ports1'>
</e-connector>
</e-connectors>
</ejs-diagram>`,
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public sourcePoint?: PointModel;
public targetPoint?: PointModel;
ngOnInit(): void {
this.sourcePoint = { x: 100, y: 100 };
this.targetPoint = { x: 300, y: 120 };
}
public ports: PointPortModel[] = [
{
offset: {
x: 1,
y: 0.5
},
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Draw,
},
]
public ports1: PathPortModel[] = [
{
offset: 0.5,
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Draw,
},
]
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Draw different connector types from port
The default connector type can be customized when drawing from ports by configuring connector defaults. This flexibility allows creation of various connector styles to match different diagram requirements:
- Straight: Direct linear connections for simple relationships
- Bezier: Curved connections for organic, flowing designs
- Orthogonal: Right-angled connections for structured layouts
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramModule, DiagramComponent, ConnectorModel, PointPortModel, PortVisibility,PortConstraints, PointModel, PathPortModel } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" [getConnectorDefaults]='getConnectorDefaults'>
<e-nodes>
<e-node id='node1' [offsetX]=250 [offsetY]=250 [width]=100 [height]=100 [ports]='ports'></e-node>
</e-nodes>
<e-connectors>
<e-connector id='connector' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [ports]='ports1'>
</e-connector>
</e-connectors>
</ejs-diagram>`,
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public sourcePoint?: PointModel;
public targetPoint?: PointModel;
ngOnInit(): void {
this.sourcePoint = { x: 100, y: 100 };
this.targetPoint = { x: 300, y: 120 };
}
public ports: PointPortModel[] = [
{
offset: {
x: 1,
y: 0.5
},
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Draw,
},
]
public ports1: PathPortModel[] = [
{
offset: 0.5,
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Draw,
},
]
public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = 'Bezier';
return connector;
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Port drag
Port drag functionality enables users to reposition ports by clicking and dragging with the mouse. This feature enhances diagram flexibility by allowing dynamic port placement adjustments. Enable this capability by setting the port constraints to Drag.
Port dragging is valuable when fine-tuning diagram layouts or adapting to changing connection requirements without recreating elements.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramModule, DiagramComponent, PointPortModel, PortVisibility,PortConstraints, PointModel, PathPortModel } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
// specifies the template string for the diagram component
template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px">
<e-nodes>
<e-node id='node1' [offsetX]=250 [offsetY]=250 [width]=100 [height]=100 [ports]='ports'>
<e-node-annotations>
<e-node-annotation content="Click and drag the port">
</e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
<e-connectors>
<e-connector id='connector' type='Orthogonal' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [ports]='ports1'>
</e-connector>
</e-connectors>
</ejs-diagram>`,
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public sourcePoint?: PointModel;
public targetPoint?: PointModel;
ngOnInit(): void {
this.sourcePoint = { x: 100, y: 100 };
this.targetPoint = { x: 300, y: 120 };
}
public ports: PointPortModel[] = [
{
offset: {
x: 1,
y: 0.5
},
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Drag,
},
]
public ports1: PathPortModel[] = [
{
offset: 0.5,
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Drag,
},
]
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Automatic Port Creation
The Diagram component supports dynamic port creation through user interaction. Users can create ports on nodes or connectors by clicking and dragging while holding the Control (Ctrl) key. This feature is disabled by default and requires enabling the DiagramConstraints.AutomaticPortCreation constraint.
Ports can also be removed using the same Ctrl + Click interaction, provided the port is not connected to any connector. This prevents accidental disconnection of active connections.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import {
DiagramModule, DiagramComponent, NodeModel, DiagramConstraints,
NodeConstraints, SnapConstraints, SnapSettingsModel
} from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [DiagramModule],
providers: [],
standalone: true,
selector: "app-container",
// specifies the template string for the diagram component with constraints
template: `<ejs-diagram #diagram id="diagram" width="100%" height="500px" [nodes]='nodes'
[constraints]='diagramConstraints' [snapSettings]='snapSettings'>
</ejs-diagram>`
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
// Enable AutomaticPortCreation
public diagramConstraints: DiagramConstraints = DiagramConstraints.Default |
DiagramConstraints.AutomaticPortCreation;
public snapSettings: SnapSettingsModel = { constraints: SnapConstraints.None };
public nodes: NodeModel[] = [
{
id: 'node1', width: 100, height: 100, offsetX: 150, offsetY: 200, style: { fill: 'cornflowerblue' },
constraints: NodeConstraints.Default &
~(NodeConstraints.InConnect | NodeConstraints.OutConnect)
},
{
id: 'node2', width: 100, height: 100, offsetX: 400, offsetY: 200, style: { fill: 'cornflowerblue' },
constraints: NodeConstraints.Default &
~(NodeConstraints.InConnect | NodeConstraints.OutConnect)
},
];
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Port tooltip
Port tooltips provide contextual information when users hover over ports, improving usability and user guidance. Enable this feature by setting the port constraints to Tooltip.
Tooltips are especially beneficial in complex diagrams where ports may not be immediately recognizable or when additional context helps users understand port functionality.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramModule, DiagramComponent, PointPortModel, PortVisibility,PortConstraints, PointModel, PathPortModel } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
// specifies the template string for the diagram component
template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" >
<e-nodes>
<e-node id='node1' [offsetX]=250 [offsetY]=250 [width]=100 [height]=100 [ports]='ports'>
<e-node-annotations>
<e-node-annotation content="Hover over port to see tooltip">
</e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
<e-connectors>
<e-connector id='connector' type='Orthogonal' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [ports]='ports1'>
</e-connector>
</e-connectors>
</ejs-diagram>`,
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public sourcePoint?: PointModel;
public targetPoint?: PointModel;
ngOnInit(): void {
this.sourcePoint = { x: 100, y: 100 };
this.targetPoint = { x: 300, y: 120 };
}
public ports: PointPortModel[] = [
{
offset: {
x: 1,
y: 0.5
},
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.ToolTip,
tooltip: { content: 'node port tooltip' },
},
]
public ports1: PathPortModel[] = [
{
offset: 0.5,
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.ToolTip,
tooltip: { content: 'connector port tooltip' },
},
]
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Events
Port interactions trigger specific events that enable custom handling and application logic. These events provide hooks for implementing validation, logging, or custom behaviors during port operations.
| Event | Description | Use Cases |
|---|---|---|
Click |
Triggers when a port is clicked | Custom selection logic, context menus |
Element Draw |
Triggers when drawing a connector from a port | Validation, custom connector properties |
Position Change |
Triggers when a port is dragged | Position validation, layout updates |
Connection Change |
Triggers when a connector connects or disconnects from a port | Relationship tracking, data validation |
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { AnnotationAlignment, DiagramModule, DiagramComponent, PointPortModel, PortVisibility, PortConstraints, PointModel, PathPortModel, IClickEventArgs, IElementDrawEventArgs, IDraggingEventArgs, IConnectionChangeEventArgs, Connector } from '@syncfusion/ej2-angular-diagrams';
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
// specifies the template string for the diagram component
template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" (click)="onClick($event)"
(positionChange)="onPositionChange($event)"
(connectionChange)="onConnectionChange($event)"
(elementDraw)="onElementDraw($event)">
<e-nodes>
<e-node id='node1' [offsetX]=250 [offsetY]=250 [width]=100 [height]=100 [ports]='ports'>
<e-node-annotations>
<e-node-annotation content="draw port" [offset]='offset1'>
</e-node-annotation>
<e-node-annotation content="darg port" [offset]='offset2'>
</e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
<e-connectors>
<e-connector id='connector' type='Orthogonal' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [ports]='ports1'>
<e-connector-annotations>
<e-connector-annotation content='Draw port' [alignment] ='alignment' [displacement]='displacement'>
</e-connector-annotation>
<e-connector-annotation content='Drag port' [offset]= 0.7 [displacement]='displacement' [alignment] ='alignment'>
</e-connector-annotation>
</e-connector-annotations>
</e-connector>
</e-connectors>
</ejs-diagram>`,
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public sourcePoint?: PointModel;
public targetPoint?: PointModel;
public offset1?: PointModel;
public offset2?: PointModel;
public displacement?: PointModel;
public alignment?: AnnotationAlignment;
ngOnInit(): void {
this.sourcePoint = { x: 100, y: 100 };
this.targetPoint = { x: 300, y: 120 };
this.offset1 = { x: 0, y: 0.7};
this.offset2 = { x: 1, y: 0.7};
this.displacement={x:0,y:10};
this.alignment = 'After';
}
public ports: PointPortModel[] = [
{
id:'p1',
offset: {
x: 0,
y: 0.5
},
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Draw,
},
{
id:'p2',
offset: {
x: 1,
y: 0.5
},
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Drag,
},
]
public ports1: PathPortModel[] = [
{
id:'p1',
offset: 0.5,
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Draw,
},
{
id:'p2',
offset: 0.8,
visibility: PortVisibility.Visible,
constraints: PortConstraints.Default | PortConstraints.Drag,
},
]
public onClick(args: IClickEventArgs): void {
console.log('clicked');
// customize
}
public onElementDraw(args: IElementDrawEventArgs): void {
if (args.state === 'Start' && args.source instanceof Connector) {
args.cancel = true; // Prevents connector drawing from connector port
}
// customize as needed
console.log('Element draw event');
}
public onPositionChange(args: IDraggingEventArgs): void {
console.log('Position change');
// customize as needed
}
public onConnectionChange(args: IConnectionChangeEventArgs): void {
console.log('Connection change');
// customize as needed
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));