ng-Diagram Angular Guide: Create Custom Nodes and Drag-and-Drop Palette
H ey devs 👋

ng-diagram Angular Guide: Create Custom Nodes and Drag-and-Drop Palette
ng-Diagram Angular Guide: Create Custom Nodes and Drag-and-Drop Palette
H ey devs 👋
It’s a continuity of the earlier blog we made using Angular + ng-Diagram. But this is a bit deeper into the library by creating custom node components and making them used in the flowchart. To explain it clearly, I created an application to draw a family tree using the custom node components.
Explore more about ng-Diagram by clicking here. 🔗
Not a Medium member? You can read the full article for free by clicking here. 🔗
As explored in the earlier blog, we have our library installed in our Angular application.
Let’s create a component to implement the custom node.
Use Case:
Creating a custom node component indicates the male and the female. Create a playground component which includes the palette and the ng-Diagram placeholder to drag and drop and create nice family tree.
Step 1:
Create two components named "male-node" and "female-node." Both the implementations will be the same, so I will explain one of the components.
import { Component, input } from '@angular/core';
import {
NgDiagramNodeSelectedDirective,
type NgDiagramNodeTemplate,
NgDiagramPortComponent,
type Node,
} from 'ng-diagram';
@Component({
imports: [NgDiagramPortComponent],
selector: 'app-male',
hostDirectives: [{ directive: NgDiagramNodeSelectedDirective, inputs: ['node'] }],
template: `
<div
class="bg-white border-2 border-slate-200 rounded-xl shadow-sm min-w-[200px] max-h-[60px] relative flex items-center justify-center p-4"
>
<div
class="absolute -top-3 -right-3 bg-white border-2 border-slate-200 rounded-full p-1 shadow-[0_2px_4px_rgba(0,0,0,0.05)] pointer-events-none flex items-center justify-center"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-4 h-4 text-blue-600"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="10" cy="14" r="5" />
<line x1="13.5" y1="10.5" x2="19" y2="5" />
<polyline points="15 5 19 5 19 9" />
</svg>
</div>
<div
contenteditable="true"
class="w-full text-center text-lg font-semibold text-slate-800 outline-none focus:bg-blue-50/50 rounded transition-colors px-2 py-1 truncate"
(keydown.enter)="$event.preventDefault()"
>
{{ node().data?.['label'] || 'Enter Name' }}
</div>
</div>
<ng-diagram-port [side]="'left'" [type]="'both'" [id]="'port-left'" />
<ng-diagram-port [side]="'right'" [type]="'both'" [id]="'port-right'" />
<ng-diagram-port [side]="'top'" [type]="'both'" [id]="'port-top'" />
<ng-diagram-port [side]="'bottom'" [type]="'both'" [id]="'port-bottom'" />
`,
styles: [],
})
export class MaleNode implements NgDiagramNodeTemplate {
node = input.required<Node<any>>();
}
- Import the NgDiagramPortComponent in your component. This will help us to use the <ng-diagram-port> in our custom node component.
- In the hostDirectives define the { directive: NgDiagramNodeSelectedDirective, inputs: [‘node’] } This will automatically apply selection styles.
- The main part of this is to implement the NgDiagramNodeTemplate; this will help us to indicate that the node is an input we have to define.
The NgDiagramPortComponent represents a single port on a node within the diagram. ng-diagram-port will take a few parameters as input to fulfill your requirement.
- side — The side of the node where the port is rendered (e.g., top, right, bottom, left).
- type — The type of the port (e.g., source, target, both).
- id—The unique identifier for the port.
That’s it, quite simple, right? Now we need to register it in your playground and start playing with it.
Step 2:
Create a playground component. inside that we are going to create a palette and area for the ng-Diagram.
<div class="flex h-screen w-full overflow-hidden bg-slate-50">
<!-- Sidebar / Palette -->
<div class="w-64 bg-white border-r border-slate-200 shadow-sm flex flex-col z-10">
<div class="p-4 border-b border-slate-100">
<h2 class="font-semibold text-slate-800">Family Tree</h2>
<p class="text-xs text-slate-500 mt-1">Let's drag and drop and create your family tree</p>
</div>
<div class="p-4 flex flex-col gap-4 overflow-y-auto">
@for (item of paletteItems; track item.type) {
<ng-diagram-palette-item [item]="item" class="cursor-grab active:cursor-grabbing block">
<!-- Sidebar Button Style -->
<div class="bg-white border-2 border-slate-200 rounded-xl shadow-sm p-3 flex items-center justify-between hover:border-slate-400 hover:shadow-md transition-all">
<span class="text-sm font-medium text-slate-700">{{ item.data['label'] }} Node</span>
<div class="w-6 h-6 rounded bg-slate-100 flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 text-slate-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
</svg>
</div>
</div>
<!-- Live Drag Preview -->
<ng-diagram-palette-item-preview>
<div class="bg-white border-2 border-slate-400 rounded-xl shadow-xl min-w-[200px] min-h-[60px] flex items-center justify-center p-4 opacity-90">
<span class="font-semibold text-slate-800">{{ item.data['label'] }}</span>
</div>
</ng-diagram-palette-item-preview>
</ng-diagram-palette-item>
}
</div>
</div>
<!-- Diagram Area -->
<div class="flex-1 relative">
<ng-diagram [model]="model" [nodeTemplateMap]="nodeTemplateMap" class="w-full h-full block">
<ng-diagram-background />
</ng-diagram>
</div>
</div>
import { Component } from '@angular/core';
import {
initializeModel,
NgDiagramBackgroundComponent,
NgDiagramComponent,
NgDiagramNodeTemplateMap,
provideNgDiagram,
NgDiagramPaletteItemComponent,
NgDiagramPaletteItemPreviewComponent,
type NgDiagramPaletteItem
} from 'ng-diagram';
import { FemaleNode } from '../../component/female-node/female-node';
import { MaleNode } from '../../component/male-node/male-node';
@Component({
selector: 'app-family-tree',
imports: [
NgDiagramComponent,
NgDiagramBackgroundComponent,
NgDiagramPaletteItemComponent,
NgDiagramPaletteItemPreviewComponent
],
templateUrl: './family-tree.html',
styleUrl: './family-tree.css',
providers : [
provideNgDiagram()
]
})
export class FamilyTree {
nodeTemplateMap = new NgDiagramNodeTemplateMap([
['male', MaleNode],
['female', FemaleNode],
]);
paletteItems: NgDiagramPaletteItem[] = [
{
type: 'male',
data: { label: 'Male' },
size: { width: 250, height: 100 },
autoSize: false
},
{
type: 'female',
data: { label: 'Female' },
size: { width: 250, height: 100 },
autoSize: false
}
];
protected readonly model = initializeModel({
nodes: [
{
id: '3',
position: { x: 200, y: 230 },
autoSize: false,
type: 'male',
data: {},
},
{
id: '4',
position: { x: 400, y: 400 },
autoSize: false,
type: 'female',
data: {},
},
],
edges: [],
});
}
- NgDiagramComponent — Main diagram component for rendering flow diagrams with nodes and edges
- NgDiagramBackgroundComponent — responsible for rendering the background of the diagram
- NgDiagramPaletteItemComponent — represents a single item in the diagram palette
- NgDiagramPaletteItemPreviewComponent — responsible for rendering a live preview of a palette item when it is being dragged or hovered in the palette.
- provideNgDiagram() — Provides all the services required for ng-diagram to function
Our playground structure will be on the left side; the palette will be placed, and our custom node components are listed there, and on the right side, the ng-diagram component will be placed.
If you see the template file, the ng-diagram-palette-item will be iterated, and each node will be passed as input to the components by the input (item).
paletteItems—is the list of palette items in the structure of NgDiagramPaletteItem[].
while drag and drop, based on the type defined in the item (each palette item). The node will be rendered in the main diagram. To render our custom node component, we need to register it.
nodeTemplateMap = new NgDiagramNodeTemplateMap([
['male', MaleNode],
['female', FemaleNode],
]);
Make sure the type you defined in the palette items should be listed in the NgDiagramNodeTemplateMap as well.
That’s it. Creating a custom drag-and-drop flow diagram designer is done.

ng-Diagram custom node
Want to explore the code in detail or try it out locally? Check out the full working example on GitHub: 👉 Source Code: ng-diagram
Thanks for reading! If this was helpful, consider clapping 👏 and following for more full-stack tips. Got questions or suggestions? Drop them in the comments below!
✍️ Author: **Vetriselvan Panneerselvam**
👨💻 Full Stack Developer | 💡 Code Enthusiast | 📚 Lifelong Learner | ✍️ Tech Blogger | 🌍 Freelance Developer
메타데이터
- post_id
- 0835c5d66a85
- slug
- ng-diagram-angular-guide-create-custom-nodes-and-drag-and-drop-palette-0835c5d66a85
- url
- https://medium.com/@vetriselvan_11/ng-diagram-angular-guide-create-custom-nodes-and-drag-and-drop-palette-0835c5d66a85
- canonical_url
- https://medium.com/@vetriselvan_11/ng-diagram-angular-guide-create-custom-nodes-and-drag-and-drop-palette-0835c5d66a85
- author_url
- https://medium.com/@vetriselvan_11
- status
- ok
- fetched_at
- 2026-08-10 06:16:44