Skip to content

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.

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' },
},
],
});
}

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;
}

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>();
}

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.

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: [],
},
},
],
});
}

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 element
  • data-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" />

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;
};