Getting Started with Angular Diagram Component
28 Jan 202624 minutes to read
This section explains how to create your first diagram and introduces the basic features of the Diagram component.
Ready to streamline your Syncfusion® Angular development? Discover the full potential of Syncfusion® Angular components with Syncfusion® AI Coding Assistant. Effortlessly integrate, configure, and enhance your projects with intelligent, context-aware code suggestions, streamlined setups, and real-time insights—all seamlessly integrated into your preferred AI-powered IDEs like VS Code, Cursor, Syncfusion® CodeStudio and more. Explore Syncfusion® AI Coding Assistant
Prerequisites
System requirements for Syncfusion Angular UI components
Dependencies
The following dependencies are required to use the Diagram component in your application:
|-- @syncfusion/ej2-angular-diagrams
|-- @syncfusion/ej2-base
|-- @syncfusion/ej2-data
|-- @syncfusion/ej2-navigations
|-- @syncfusion/ej2-inputs
|-- @syncfusion/ej2-popups
|-- @syncfusion/ej2-buttons
|-- @syncfusion/ej2-lists
|-- @syncfusion/ej2-splitbuttonsSetup Angular Environment
Use Angular CLI to set up your Angular applications. Install Angular CLI globally with the following command:
npm install -g @angular/cliCreate an Angular Application
Generate a new Angular project using the Angular CLI command below.
ng new my-diagram-appWhen prompted, choose your preferred stylesheet format:
? Which stylesheet system would you like to use?
> CSS [ https://developer.mozilla.org/docs/Web/CSS ]
Tailwind CSS [ https://tailwindcss.com ]
Sass (SCSS) [ https://sass-lang.com/documentation/syntax#scss ]
Sass (Indented) [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]
Less [ http://lesscss.org ]By default, CSS is used. For SCSS, see the Sass guide.
Then navigate to the project directory:
cd my-diagram-appInstalling Syncfusion® Diagram package
All Essential JS 2 packages are available on npmjs.com. Install the Angular Diagram package:
npm install @syncfusion/ej2-angular-diagrams --saveNOTE
The –save flag adds the package to the dependencies section of
package.json.
Registering Diagram Module
Import the Diagram module in src\app\app.ts from the package @syncfusion/ej2-angular-diagrams and enable it for your component.
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';
import { Component } from "@angular/core";
@Component({
// Enable the DiagramModule in this standalone component
imports: [ DiagramModule ],
selector: 'app-root',
})
export class App {}Add Required Styles
Combined CSS files are available in the Essential JS 2 package root folder. Reference the CSS files in src\styles.css:
@import "../node_modules/@syncfusion/ej2-diagrams/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-base/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/tailwind3.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/tailwind3.css";Render the Diagram component
Add the <ejs-diagram> selector to the template in src\app\app.ts, and specify a height to ensure the diagram renders correctly.
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams';
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
//Import Diagram module
imports: [ DiagramModule ],
// specifies the template string for the diagram component
template: `<ejs-diagram id="diagram" width="100%" height="580px"></ejs-diagram>`,
})
export class App {}Run the Application
Start the dev server:
npm startOpen the browser using the printed URL to see the empty diagram.
NOTE
The selector specified in the @Component decorator of the app.ts file must match the custom element tag used in the
index.htmlfile. For example, if your @Component decorator includes the selector “app-root”, yourindex.htmlfile should include an element<app-root></app-root>.
Enabling Feature Modules (Services)
Diagram features are provided as services. To use a particular feature, Import the ones you need and add them to the component’s providers.
Example: enable UndoRedoService and SnappingService:
import { Component } from "@angular/core";
// Import the services
import {
DiagramModule,
UndoRedoService,
SnappingService
} from '@syncfusion/ej2-angular-diagrams';
@Component({
selector: 'app-root',
imports: [ DiagramModule ],
// Register the services
providers: [ UndoRedoService, SnappingService ],
template: `<ejs-diagram width="100%" height="500px">
<e-nodes>
<e-node [offsetX]="100" [offsetY]="100" [width]="100" [height]="100">
</e-node>
</e-nodes>
</ejs-diagram>`,
})
export class App { }The following list describes the module names and their descriptions:
-
BpmnDiagramsService- Inject this provider to add built-in BPMN shapes to diagrams. -
ConnectorBridgingService- Inject this provider to add bridges to connectors. -
ConnectorEditingService- Inject this provider to edit connector segments. -
ComplexHierarchicalTreeService- Inject this provider for complex hierarchical tree structures. -
DataBindingService- Inject this provider to populate nodes from a given data source. -
DiagramContextMenuService- Inject this provider to manipulate the context menu. -
HierarchicalTreeService- Inject this provider to use hierarchical tree structures. -
LayoutAnimationService- Inject this provider to add animation to layouts. -
MindMapService- Inject this provider to use mind map layouts. -
PrintAndExportService- Inject this provider to print or export diagram objects. -
RadialTreeService- Inject this provider to use radial tree structures. -
SnappingService- Inject this provider to enable object snapping. -
SymmetricLayoutService- Inject this provider to render layouts in a symmetrical method. -
UndoRedoService- Inject this provider to revert and restore changes. -
Ej1SerializationService- Inject this provider to load EJ1 diagram JSON in EJ2 diagrams.
Tip: Import your services and add them to the providers list in app.config.ts to make them available throughout the app.
Defining Basic Diagram
The example below shows a basic diagram that renders an empty diagram canvas:
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams'
import { Component } from "@angular/core";
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
// specifies the template string for the diagram component
template: `<ejs-diagram id="diagram" width="100%" height="580px"></ejs-diagram>`
})
export class AppComponent {}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Basic Diagram elements
Diagrams are built using the following core elements:
-
Node: Visualizes graphical objects that can be arranged and manipulated on a diagram page. -
Connector: Represents relationships between two nodes. Three types of connectors are provided:- Orthogonal
- Bezier
- Straight
-
Port: Acts as connection points on nodes or connectors, allowing connections only at specific points. -
Annotation: Displays additional information by adding text or labels on nodes and connectors.
Flow Diagram
Create and Add Node to the diagram
Create and add a node (JSON data) with specific position, size, label, and shape:
import { DiagramComponent, DiagramModule } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from "@angular/core";
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
template: `<ejs-diagram id="diagram" width="100%" height="580px" mode="SVG">
<e-nodes>
<e-node id='node1' [height]=60 [width]=100 [offsetX]=300 [offsetY]=80 >
<e-node-annotations>
<e-node-annotation content='Start'></e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
</ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
ngOnInit(): void {
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Apply shape and style to node
The Syncfusion diagram component provides support to render many built-in shapes. Refer to Shapes to learn about built-in shapes.
Customize the appearance of a node by changing its fill color, strokeColor, strokeWidth, borderColor, borderWidth, strokeDashArray, opacity, and shadow properties:
import { DiagramComponent, DiagramModule, FlowShapeModel } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from "@angular/core";
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
template: `<ejs-diagram id="diagram" width="100%" height="580px" mode="SVG">
<e-nodes>
<e-node id='node1' [height]=60 [width]=100 [offsetX]=300 [offsetY]=80 [shape]='shape' [style]='style' [borderColor]='borderColor' [borderWidth]='borderWidth'>
<e-node-annotations>
<e-node-annotation content='Start'></e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
</ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public Diagram?: DiagramComponent;
public shape:FlowShapeModel = { type: 'Flow', shape: 'Terminator'};
public borderColor = 'orange';
public borderWidth = 10;
public style = {fill:'red',strokeColor:'green',strokeWidth:5,strokeDashArray:'2 2'};
ngOnInit(): void {
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Add other flowchart nodes to the diagram
Add multiple nodes with different shapes to create a comprehensive diagram:
import { DiagramComponent, DiagramModule } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from "@angular/core";
import {
FlowShapeModel,
NodeModel,
ConnectorModel,
} from "@syncfusion/ej2-angular-diagrams";
@Component({
imports: [
DiagramModule
],
providers: [ ],
standalone: true,
selector: "app-container",
template: `<ejs-diagram id="diagram" width="100%" height="580px" [getNodeDefaults]='nodeDefaults' [getConnectorDefaults]='connectorDefaults'>
<e-nodes>
<e-node id='node1' [offsetX]=300 [offsetY]=50 [shape]='terminator'>
<e-node-annotations>
<e-node-annotation content='Start'></e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='node2' [offsetX]=300 [offsetY]=140 [shape]='process'>
<e-node-annotations>
<e-node-annotation content='var i = 0;'></e-node-annotation>
</e-node-annotations>
</e-node>
<e-node id='node3' [offsetX]=300 [offsetY]=230 [shape]='decision'>
<e-node-annotations>
<e-node-annotation content='i < 10?'></e-node-annotation>
</e-node-annotations>
</e-node>
</e-nodes>
</ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public terminator?: FlowShapeModel;
public process?: FlowShapeModel;
public decision?: FlowShapeModel;
public nodeDefaults(node: NodeModel): NodeModel {
node.height = 50;
node.width = 140;
node.style = {fill:'skyblue', strokeColor: 'skyblue'};
return node;
}
public connectorDefaults(obj: ConnectorModel): ConnectorModel {
obj.type = "Orthogonal";
obj.targetDecorator = { shape: "Arrow", width: 10, height: 10 };
return obj;
}
ngOnInit(): void {
this.terminator = { type: 'Flow', shape: 'Terminator' };
this.process = { type: 'Flow', shape: 'Process' };
this.decision = { type: 'Flow', shape: 'Decision' };
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Connect flow chart nodes
Connect nodes by adding connectors using the connectors property of the diagram. Reference the source and target endpoints using the sourceID and targetID properties. Combine the required nodes and connectors to form a complete flow diagram:
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Set default values for all nodes and connectors using the getNodeDefaults and getConnectorDefaults properties, respectively. For example, if all nodes have the same width and height, move such properties into getNodeDefaults.
Automatic Organization Chart
The previous ‘Flow Diagram’ section explained how to create a diagram manually. This section demonstrates how to create and position diagrams automatically using data binding.
Business object (Employee information)
Define Employee Information as JSON data. The following code example shows an employee array where Name serves as a unique identifier and ReportingPerson identifies the person to whom an employee reports in the organization:
public data: Object[] = [
{
Name: "Elizabeth",
Role: "Director"
},
{
Name: "Christina",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Yoshi",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Philip",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Yang",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Roland",
ReportingPerson: "Yang",
Role: "Lead"
},
{
Name: "Yvonne",
ReportingPerson: "Yang",
Role: "Lead"
}
];Map data source
Configure the above “Employee Information” with the diagram so that nodes and connectors are automatically generated using the mapping properties. The following code example demonstrates how to use dataSourceSettings to map id and parentId with the corresponding property names of employee information:
@Component({
selector: "app-root",
template: `<ejs-diagram id="diagram" width="100%" height="580px" [dataSourceSettings]='dataSourceSettings'></ejs-diagram>`
})
export class App {
@ViewChild("diagram")
public diagram!: DiagramComponent;
public data: Object[] = [
{
Name: "Elizabeth",
Role: "Director"
},
{
Name: "Christina",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Yoshi",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Philip",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Yang",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Roland",
ReportingPerson: "Yang",
Role: "Lead"
},
{
Name: "Yvonne",
ReportingPerson: "Yang",
Role: "Lead"
}
];
public dataSourceSettings: DataSourceModel = {
id: "Name",
parentId: "ReportingPerson",
dataManager: new DataManager(this.data as JSON[]),
};
}Rendering layout with Datasource
To create an organizational chart, set the type of layout as OrganizationalChart. The following code example shows how DataManager generates layouts based on the DataSourceSettings of the Diagram:
import { ConnectorModel, DataBinding, DataSourceModel, Diagram, DiagramComponent, DiagramModule,HierarchicalTree,LayoutModel, NodeModel, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from "@angular/core";
import { DataManager } from "@syncfusion/ej2-data";
export interface EmployeeInfo {
Name: string;
Role: string;
color: string;
}
Diagram.Inject(DataBinding,HierarchicalTree);
@Component({
imports: [
DiagramModule
],
standalone: true,
selector: "app-container",
template: `<ejs-diagram id="diagram" width="100%" height="580px" [layout]='layout' [dataSourceSettings]='dataSourceSettings' [getNodeDefaults]='nodeDefaults' [getConnectorDefaults]='connectorDefaults'>
</ejs-diagram>`
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public data: Object[] = [
{
Name: "Elizabeth",
Role: "Director",
ReportingPerson:null
},
{
Name: "Christina",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Yoshi",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Philip",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Yang",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Roland",
ReportingPerson: "Yang",
Role: "Lead"
},
{
Name: "Yvonne",
ReportingPerson: "Yang",
Role: "Lead"
}
];
public dataSourceSettings?: DataSourceModel = {
id: "Name",
parentId: "ReportingPerson",
dataManager: new DataManager(this.data as JSON[]),
doBinding: (nodeModel: NodeModel, data: object) => {
nodeModel.annotations = [
{ content: (data as EmployeeInfo).Name, style: { color: "white" } }
];
}
};
public layout: LayoutModel = {
type:'OrganizationalChart'
};
public nodeDefaults(node: NodeModel): NodeModel {
let codes: Object = {
Director: "rgb(0, 139,139)",
Manager: "rgb(30, 30,113)",
Lead: "rgb(0, 100,0)"
};
node.width = 70;
node.height = 30;
node.annotations = [
{ content: (node.data as EmployeeInfo).Name, style: { color: "white" } }
];
((node as NodeModel).style as ShapeStyleModel).fill = (codes as any)[(node.data as EmployeeInfo).Role] as string;
return node;
}
public connectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = "Orthogonal";
connector.cornerRadius = 7;
return connector;
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));Customize employee appearance
The following code examples show how to define the default appearance of nodes and connectors. The setNodeTemplate method updates each node based on employee data:
import { ConnectorModel, DataBinding, DataSourceModel, Diagram, DiagramComponent, DiagramModule, HierarchicalTree, ImageElement, LayoutModel, NodeModel, StackPanel, TextElement } from '@syncfusion/ej2-angular-diagrams'
import { Component, ViewEncapsulation, ViewChild } from "@angular/core";
import { DataManager } from "@syncfusion/ej2-data";
export interface EmployeeInfo {
Name: string;
Role: string;
color: string;
}
Diagram.Inject(HierarchicalTree,DataBinding);
@Component({
imports: [
DiagramModule
],
standalone: true,
selector: "app-container",
template: `<ejs-diagram id="diagram" width="100%" height="580px" [layout]='layout' [dataSourceSettings]='dataSourceSettings'
[getConnectorDefaults]='connectorDefaults' [setNodeTemplate]='setNodeTemplate'>
</ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public data: Object[] = [
{
Name: "Elizabeth",
Role: "Director",
ReportingPerson:null
},
{
Name: "Christina",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Yoshi",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Philip",
ReportingPerson: "Christina",
Role: "Lead"
},
{
Name: "Yang",
ReportingPerson: "Elizabeth",
Role: "Manager"
},
{
Name: "Roland",
ReportingPerson: "Yang",
Role: "Lead"
},
{
Name: "Yvonne",
ReportingPerson: "Yang",
Role: "Lead"
}
];
public dataSourceSettings?: DataSourceModel = {
id: "Name",
parentId: "ReportingPerson",
dataManager: new DataManager(this.data as JSON[]),
};
public layout: LayoutModel = {
type:'OrganizationalChart'
};
public connectorDefaults(connector: ConnectorModel): ConnectorModel {
connector.type = "Orthogonal";
connector.cornerRadius = 7;
return connector;
}
public setNodeTemplate(node: NodeModel) {
let codes: Object = {
Director: "rgb(0, 139,139)",
Manager: "rgb(30, 30,113)",
Lead: "rgb(0, 100,0)"
};
let content = new StackPanel();
content.id = node.id + "_outerstack";
content.orientation = "Horizontal";
content.style.strokeColor = "gray";
content.style.fill = (codes as any)[(node.data as EmployeeInfo).Role] as string;
content.padding = { left: 5, right: 5, top: 5, bottom: 5}
let innerContent = new ImageElement();
innerContent.style.strokeColor = "blue";
innerContent.id = node.id + "_innerstack";
innerContent.style.fill = "skyblue";
innerContent.width = 50;
innerContent.height = 50;
let text = new TextElement();
text.id = node.id + "_text";
text.content = (node.data as EmployeeInfo).Name;
text.margin = { left: 15, right: 5, top: 5, bottom: 5}
text.style.color = "black";
content.children = [innerContent, text];
return content;
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));NOTE
Projects generated through Angular CLI automatically detect changes made to the application and compile them. You don’t need to run “npm start” for each change made to the application.