Labels
Labels are visual elements attached to edges that can display text, buttons, or any custom content. They automatically position themselves along the edge path and follow the edge as it moves or changes shape.
Each edge has a measuredLabels property that provides information about its labels and their computed position and size.
This property is read-only and should not be modified.
Using Labels in Default Edges
Section titled “Using Labels in Default Edges”To display a label on a default edge, you can add a label property to the edge’s data.
29 collapsed lines
import '@angular/compiler';
import { Component } from '@angular/core';import { initializeModel, NgDiagramBackgroundComponent, NgDiagramComponent, provideNgDiagram, type NgDiagramConfig,} from 'ng-diagram';
@Component({ imports: [NgDiagramComponent, NgDiagramBackgroundComponent], providers: [provideNgDiagram()], template: ` <div class="not-content diagram"> <ng-diagram [model]="model" [config]="config"> <ng-diagram-background /> </ng-diagram> </div> `, styles: ` .diagram { display: flex; height: var(--ng-diagram-height); border: var(--ng-diagram-border); } `,})export class DiagramComponent { config = { zoom: { zoomToFit: { onInit: true, padding: 120, }, }, } satisfies NgDiagramConfig;
model = initializeModel({ metadata: { viewport: { x: 0, y: 0, scale: 0.88 }, }, nodes: [ { id: '1', position: { x: 150, y: 150 }, data: { label: 'Node 1' }, rotatable: true, }, { id: '2', position: { x: 500, y: 150 }, data: { label: 'Node 2' } }, ], edges: [ { id: '1', source: '1', sourcePort: 'port-right', targetPort: 'port-left', target: '2', data: { label: 'Label' }, }, ], });}CSS Variables
Section titled “CSS Variables”Default labels can be styled using CSS variables. You can customize these in your global styles:
ng-diagram-default-edge-label { --edge-label-padding: 10px; --edge-label-border-radius: 8px; --edge-label-font-size: 14px; --edge-label-background-color: #f3f4f6; --edge-label-text-color: #1e293b; --edge-label-border-width: 2px; --edge-label-border-color: #334155; --edge-label-border-transition: border-color 0.1s ease-in-out;}Available CSS variables:
--edge-label-padding- Label padding--edge-label-border-radius- Label border radius--edge-label-font-size- Label font size--edge-label-background-color- Label background color--edge-label-text-color- Label text color--edge-label-border-width- Label border width--edge-label-border-color- Label border color--edge-label-border-transition- Transition for border changes
The default label also uses these semantic variables that map to the design system:
--ngd-default-edge-label-color- Label text color--ngd-default-edge-label-background-color- Label background color--ngd-default-edge-label-border-color- Label border color
The default edge applies different styles to labels based on the edge state (normal, hover, selected). You can customize these styles by modifying the following CSS:
ng-diagram-base-edge.default-edge:hover:not(.selected) { --edge-label-border-color: #2563eb;}
ng-diagram-base-edge.default-edge.selected { --edge-label-border-color: #3b82f6;}Custom Labels
Section titled “Custom Labels”To display a custom label on an edge, use the NgDiagramBaseEdgeLabelComponent in an implementation of your custom edge component:
import { Component, input } from '@angular/core';import { NgDiagramBaseEdgeComponent, NgDiagramBaseEdgeLabelComponent, type Edge, type NgDiagramEdgeTemplate,} from 'ng-diagram';
@Component({ selector: 'custom-label-edge', template: `<ng-diagram-base-edge [edge]="edge()" stroke="var(--ngd-default-edge-stroke)" > <ng-diagram-base-edge-label [id]="'custom-label'" [positionOnEdge]="0.5"> <div class="custom-label">Custom Label</div> </ng-diagram-base-edge-label> </ng-diagram-base-edge>`, styleUrl: './custom-label-edge.component.scss', imports: [NgDiagramBaseEdgeComponent, NgDiagramBaseEdgeLabelComponent],})export class CustomLabelEdgeComponent implements NgDiagramEdgeTemplate { edge = input.required<Edge>();}Label Positioning
Section titled “Label Positioning”The positionOnEdge property determines where the label appears along the edge path. It can be set to any value from 0 to 1, where 0.5 is the center of the edge. Labels automatically follow the edge path, regardless of the used routing algorithm.
Adding labels
Section titled “Adding labels”Labels can be added and modified dynamically. One way to achieve this is by using diagram’s model. The ModifiableLabelEdgeComponent (see below) shows how to map such data into an actual label implementation.
Click on an edge to select it in the example below. Then fill the label’s name and click “Set Label”.
import '@angular/compiler';
import { Component } from '@angular/core';import { FormsModule } from '@angular/forms';import { initializeModel, NgDiagramBackgroundComponent, NgDiagramComponent, NgDiagramEdgeTemplateMap, provideNgDiagram, type NgDiagramConfig,} from 'ng-diagram';import { LabelPanel } from './label-panel.component';import { ModifiableLabelEdgeComponent } from './modifiable-label-edge.component';
@Component({ selector: 'diagram', imports: [ NgDiagramComponent, FormsModule, LabelPanel, NgDiagramBackgroundComponent, ], providers: [provideNgDiagram()], template: ` <div class="not-content diagram"> <ng-diagram [model]="model" [edgeTemplateMap]="edgeTemplateMap" [config]="config" > <ng-diagram-background /> </ng-diagram> <label-panel /> </div> `, styles: ` .diagram { position: relative; display: flex; height: var(--ng-diagram-height); border: var(--ng-diagram-border); } `,})export class DiagramComponent { edgeTemplateMap = new NgDiagramEdgeTemplateMap([ ['modifiable-label', ModifiableLabelEdgeComponent], ]);
config = { zoom: { zoomToFit: { onInit: true, padding: [50, 170, 50, 50], }, }, } satisfies NgDiagramConfig;
model = initializeModel({ nodes: [ { id: 'a', position: { x: 75, y: 25 }, data: { label: 'Node 1' }, rotatable: true, }, { id: 'b', position: { x: 550, y: 175 }, data: { label: 'Node 2' } }, { id: 'c', position: { x: 75, y: 375 }, data: { label: 'Node 3' } }, ], edges: [ { id: '1', source: 'a', sourcePort: 'port-right', targetPort: 'port-left', target: 'b', type: 'modifiable-label', data: { texts: [], }, }, { id: '2', source: 'b', sourcePort: 'port-left', targetPort: 'port-right', target: 'c', type: 'modifiable-label', data: { texts: [], }, }, ], });}import { Component, computed, inject } from '@angular/core';import { FormsModule } from '@angular/forms';import { NgDiagramModelService } from 'ng-diagram';
@Component({ selector: 'label-panel', imports: [FormsModule], template: ` @if (isEdgeSelected()) { <input [(ngModel)]="label" /> } @else { Select an edge } <button (click)="onSetLabel()">Set Label</button> `,21 collapsed lines
styles: ` :host { z-index: 1; background-color: var(--ngd-node-bg-primary-default); border: var(--ng-diagram-border); position: absolute; width: 8rem; top: 1rem; right: 1rem; height: calc(100% - 2rem); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1rem;
input { width: calc(100% - 2rem); } } `,})export class LabelPanel { private modelService: NgDiagramModelService = inject(NgDiagramModelService); edges = computed(() => this.modelService.getModel().getEdges());5 collapsed lines
selectedEdge = computed(() => this.edges().find((edge) => edge.selected)); isEdgeSelected = computed(() => !!this.selectedEdge()); label = '';
onSetLabel() { const edgeToUpdate = this.edges().find((edge) => edge.selected);
if (!edgeToUpdate) { return; }
this.modelService.updateEdgeData(edgeToUpdate.id, { label: this.label, }); }}7 collapsed lines
import { Component, computed, input } from '@angular/core';import { NgDiagramBaseEdgeComponent, NgDiagramBaseEdgeLabelComponent, type Edge, type NgDiagramEdgeTemplate,} from 'ng-diagram';
@Component({ selector: 'multi-label-edge', template: `<ng-diagram-base-edge [edge]="edge()" routing="bezier" [stroke]="selected() ? 'rebeccapurple' : 'var(--ngd-default-edge-stroke)'" > @if (label()) { <ng-diagram-base-edge-label [id]="label().id" [positionOnEdge]="label().positionOnEdge" class="label" > {{ label().content }} </ng-diagram-base-edge-label> } </ng-diagram-base-edge>`, styleUrl: './modifiable-label-edge.component.scss', imports: [NgDiagramBaseEdgeComponent, NgDiagramBaseEdgeLabelComponent],})export class ModifiableLabelEdgeComponent implements NgDiagramEdgeTemplate<MultiLabelEdgeData>{3 collapsed lines
edge = input.required<Edge<MultiLabelEdgeData>>();
selected = computed(() => this.edge().selected);
label = computed(() => { const { label } = this.edge().data;
if (!label) { return; }
return { id: 'label', positionOnEdge: 0.5, content: label }; });}4 collapsed lines
type MultiLabelEdgeData = { label: string;};.label { background: var(--ngd-node-bg-primary-default); color: var(--ngd-txt-primary-default); padding: 4px 8px; border-radius: 4px; border: 1px solid var(--ngd-node-stroke-primary-default); font-size: 12px; font-weight: 500;}Handling Interactive Elements in Labels
Section titled “Handling Interactive Elements in Labels”When adding interactive elements like inputs to edge labels, dragging on these elements might trigger unwanted diagram behaviors. You can control this using special data attributes:
data-no-pan="true"- Prevents the diagram canvas from panning when the user clicks and drags on the elementdata-no-drag="true"- Prevents nodes from being dragged when the user clicks and drags on the element
<!-- Input in edge label that won't trigger diagram interactions --><input type="text" data-no-pan="true" data-no-drag="true" placeholder="Type here" />Multiple Labels
Section titled “Multiple Labels”NgDiagram supports multiple labels and they can be used to display images, shapes, or any other content. The example below demonstrates how to add multiple labels to an edge to create a flow animation.
7 collapsed lines
import { Component, computed, input } from '@angular/core';import { NgDiagramBaseEdgeComponent, NgDiagramBaseEdgeLabelComponent, type Edge, type NgDiagramEdgeTemplate,} from 'ng-diagram';
const LABEL_COUNT = 10;const ANIMATION_DURATION = 0.5;
@Component({ selector: 'multi-label-edge', template: `<ng-diagram-base-edge [edge]="edge()" routing="bezier" [stroke]="selected() ? 'rebeccapurple' : 'var(--ngd-default-edge-stroke)'" > @for (label of animatedLabels(); track label.id) { <ng-diagram-base-edge-label class="label" [id]="label.id" [positionOnEdge]="label.positionOnEdge" [style]="label.style" > </ng-diagram-base-edge-label> } </ng-diagram-base-edge>`, styles: ` @keyframes label-animation { 0% { background: aliceblue; }
100% { background: rebeccapurple; } }
.label { width: 1rem; height: 1rem; border-radius: 100%; background: aliceblue; animation: label-animation ${ANIMATION_DURATION}s ease-in-out infinite; } `, imports: [NgDiagramBaseEdgeComponent, NgDiagramBaseEdgeLabelComponent],})export class MultipleLabelsEdgeComponent implements NgDiagramEdgeTemplate<MultiLabelEdgeData>{ edge = input.required<Edge<MultiLabelEdgeData>>(); selected = computed(() => this.edge().selected);
animatedLabels = computed(() => { return Array.from({ length: LABEL_COUNT }, (_, i) => ({ id: `label-${i}`, positionOnEdge: (i + 1) / (LABEL_COUNT + 1), style: { animationDelay: `${(ANIMATION_DURATION / LABEL_COUNT) * i}s`, }, })); });}
type MultiLabelEdgeData = { label: string;};