Radial tree layout in Angular Diagram control
23 Aug 202518 minutes to read
A radial tree layout is a specialized diagram that presents hierarchical information with a central node at the core, surrounded by branches extending outward in a circular, tree-like structure. This layout is particularly effective for visualizing organizational charts, family trees, mind maps, and network relationships where understanding the relationship distance from a central concept is important.
The central node represents the main concept or topic, with child nodes arranged in concentric circles based on their hierarchical level. The layout root
property can be used to define the root node of the layout. When no root node is specified, the algorithm automatically identifies the node without any incoming edges (InEdges connector count of 0) as the root node. To create a radial tree, set the type
property of the layout to RadialTree
.
The RadialTree layout provides comprehensive support for controlling node spacing and arrangement. The horizontalSpacing
and verticalSpacing
properties allow precise control over the space between nodes, measured in pixels. The arrangement creates an expanding concentric pattern where radial proximity to the root node indicates the hierarchical level.
Prerequisites
To use radial tree layouts, ensure the following modules are injected into the diagram:
-
RadialTree
module for layout functionality -
DataBinding
module (when using data source)
Radial tree with DataSource
Creating a radial tree layout with a data source provides automatic node generation and connection management. This approach is ideal when working with structured data objects that define hierarchical relationships.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, SnapSettingsModel, LayoutModel, DataSourceModel, DataBinding,
DiagramModule, RadialTreeService, DataBindingService, RadialTree, ConnectorModel, DecoratorModel } from '@syncfusion/ej2-angular-diagrams';
import { DataManager, Query } from '@syncfusion/ej2-data';
Diagram.Inject(DataBinding, RadialTree);
@Component({
imports: [DiagramModule],
providers: [RadialTreeService, DataBindingService],
standalone: true,
selector: "app-container",
template: `<ejs-diagram #diagram id="diagram" width="100%" height="590px" [snapSettings]="snapSettings" [getNodeDefaults]="getNodeDefaults"
[getConnectorDefaults]="getConnectorDefaults" [layout]="layout" [dataSourceSettings]="dataSourceSettings"> </ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public snapSettings?: SnapSettingsModel;
public items?: DataManager;
public layout?: LayoutModel;
public dataSourceSettings?: DataSourceModel;
//Initializes data source
public data: object[] = [
{
Id: 'parent',
Name: 'Maria Anders',
Designation: 'Managing Director'
},
{
Id: '1',
Name: 'Ana Trujillo',
Designation: 'Project Manager',
ReportingPerson: 'parent',
},
{
Id: '2',
Name: 'Lino Rodri',
Designation: 'Project Manager',
ReportingPerson: 'parent',
},
{
Id: '3',
Name: 'Philip Cramer',
Designation: 'Project Manager',
ReportingPerson: 'parent',
},
{
Id: '4',
Name: 'Pedro Afonso',
Designation: 'Project Manager',
ReportingPerson: 'parent',
},
{
Id: '15',
Name: 'Paul Henriot',
Designation: 'Project Manager',
ReportingPerson: 'parent',
},
{
Id: '18',
Name: 'Laura Callahan',
Designation: 'Project Manager',
ReportingPerson: 'parent',
},
{
Id: '5',
Name: 'Anto Moreno',
Designation: 'Project Lead',
ReportingPerson: '1',
},
{
Id: '6',
Name: 'Elizabeth Roel',
Designation: 'Project Lead',
ReportingPerson: '1',
},
{
Id: '7',
Name: 'Aria Cruz',
Designation: 'Project Lead',
ReportingPerson: '18',
},
{
Id: '8',
Name: 'Eduardo Roel',
Designation: 'Project Lead',
ReportingPerson: '18',
},
{
Id: '9',
Name: 'Howard Snyd',
Designation: 'Project Lead',
ReportingPerson: '2',
},
{
Id: '10',
Name: 'Daniel Tonini',
Designation: 'Project Lead',
ReportingPerson: '2',
},
{
Id: '11',
Name: 'Nardo Batista',
Designation: 'Project Lead',
ReportingPerson: '3',
},
{
Id: '12',
Name: 'Michael Holz',
Designation: 'Project Lead',
ReportingPerson: '3',
},
{
Id: '13',
Name: 'Kloss Perrier',
Designation: 'Project Lead',
ReportingPerson: '4',
},
{
Id: '14',
Name: 'Liz Nixon',
Designation: 'Project Lead',
ReportingPerson: '4',
},
{
Id: '16',
Name: 'Paula Parente',
Designation: 'Project Lead',
ReportingPerson: '15',
},
{
Id: '17',
Name: 'Matti Kenna',
Designation: 'Project Lead',
ReportingPerson: '15',
}
];
//Sets the default properties for nodes
public getNodeDefaults(node: NodeModel): NodeModel {
node.height = 20;
node.width = 20;
return node;
}
//Sets the default properties for connectors
public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
(connector.targetDecorator as DecoratorModel).shape = 'None';
connector.type = 'Straight';
return connector;
}
ngOnInit(): void {
this.snapSettings = { constraints: 0 }
this.items = new DataManager(this.data as JSON[], new Query().take(7));
//Uses layout to auto-arrange nodes on the Diagram page
this.layout = {
//set layout type
type: 'RadialTree',
root: 'parent'
}
//Configures data source for Diagram
this.dataSourceSettings = {
id: 'Id',
parentId: 'ReportingPerson',
dataSource: this.items
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Note: When converting a data source into a radial layout, inject both DataBinding and RadialTree modules in the diagram component.
Radial tree with nodes and connectors
For scenarios requiring manual control over node creation and positioning, the radial tree layout can be applied to explicitly defined nodes and connectors. This approach offers greater flexibility for custom node styling and specific layout requirements.
import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel, SnapSettingsModel, LayoutModel, DiagramModule,
RadialTreeService, DataBindingService, DataBinding, RadialTree, DecoratorModel} from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(DataBinding, RadialTree);
@Component({
imports: [DiagramModule],
providers: [RadialTreeService, DataBindingService],
standalone: true,
selector: "app-container",
template: `<ejs-diagram #diagram id="diagram" width="100%" height="590px" [nodes]="nodes" [connectors]="connectors"
[getNodeDefaults]="getNodeDefaults" [getConnectorDefaults]="getConnectorDefaults" [snapSettings]="snapSettings" [layout]="layout"> </ejs-diagram>`,
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
@ViewChild("diagram")
public diagram?: DiagramComponent;
public snapSettings?: SnapSettingsModel;
public layout?: LayoutModel;
//Initializes Nodes for diagram
public nodes: NodeModel[] = [
{ id: 'Maria Anders' },
{ id: 'Ana Trujillo' },
{ id: 'Lino Rodri' },
{ id: 'Philip Cramer' },
{ id: 'Pedro Afonso' },
{ id: 'Paul Henriot' },
{ id: 'Laura Callahan' },
{ id: 'Anto Moreno' },
{ id: 'Elizabeth Roel' },
{ id: 'Aria Cruz' },
{ id: 'Eduardo Roel' },
{ id: 'Howard Snyd' },
{ id: 'Daniel Tonini' },
{ id: 'Nardo Batista' },
{ id: 'Michael Holz' },
{ id: 'Kloss Perrier' },
{ id: 'Liz Nixon' },
{ id: 'Paula Parente' },
{ id: 'Matti Kenna' },
];
//Initializes Connectors for diagram
public connectors: ConnectorModel[] = [
{
id: 'Maria Anders-Ana Trujillo',
sourceID: 'Maria Anders',
targetID: 'Ana Trujillo',
},
{
id: 'Maria Anders-Lino Rodri',
sourceID: 'Maria Anders',
targetID: 'Lino Rodri',
},
{
id: 'Maria Anders-Philip Cramer',
sourceID: 'Maria Anders',
targetID: 'Philip Cramer',
},
{
id: 'Maria Anders-Pedro Afonso',
sourceID: 'Maria Anders',
targetID: 'Pedro Afonso',
},
{
id: 'Maria Anders-Paul Henriot',
sourceID: 'Maria Anders',
targetID: 'Paul Henriot',
},
{
id: 'Maria Anders-Laura Callahan',
sourceID: 'Maria Anders',
targetID: 'Laura Callahan',
},
{
id: 'Ana Trujillo-Anto Moreno',
sourceID: 'Ana Trujillo',
targetID: 'Anto Moreno',
},
{
id: 'Ana Trujillo-Elizabeth Roel',
sourceID: 'Ana Trujillo',
targetID: 'Elizabeth Roel',
},
{
id: 'Laura Callahan-Aria Cruz',
sourceID: 'Laura Callahan',
targetID: 'Aria Cruz',
},
{
id: 'Laura Callahan-Eduardo Roel',
sourceID: 'Laura Callahan',
targetID: 'Eduardo Roel',
},
{
id: 'Lino Rodri-Howard Snyd',
sourceID: 'Lino Rodri',
targetID: 'Howard Snyd',
},
{
id: 'Lino Rodri-Daniel Tonini',
sourceID: 'Lino Rodri',
targetID: 'Daniel Tonini',
},
{
id: 'Philip Cramer-Nardo Batista',
sourceID: 'Philip Cramer',
targetID: 'Nardo Batista',
},
{
id: 'Philip Cramer-Michael Holz',
sourceID: 'Philip Cramer',
targetID: 'Michael Holz',
},
{
id: 'Pedro Afonso-Kloss Perrier',
sourceID: 'Pedro Afonso',
targetID: 'Kloss Perrier',
},
{
id: 'Pedro Afonso-Liz Nixon',
sourceID: 'Pedro Afonso',
targetID: 'Liz Nixon',
},
{
id: 'Paul Henriot-Paula Parente',
sourceID: 'Paul Henriot',
targetID: 'Paula Parente',
},
{
id: 'Paul Henriot-Matti Kenna',
sourceID: 'Paul Henriot',
targetID: 'Matti Kenna',
}
];
//Sets the default properties for nodes
public getNodeDefaults(node: NodeModel): NodeModel {
node.height = 20;
node.width = 20;
return node;
}
//Sets the default properties for connectors
public getConnectorDefaults(connector: ConnectorModel): ConnectorModel {
(connector.targetDecorator as DecoratorModel).shape = 'None';
connector.type = 'Straight';
return connector;
}
ngOnInit(): void {
this.snapSettings = { constraints: 0 }
//Uses layout to auto-arrange nodes on the Diagram page
this.layout = {
//set the type as Radial Tree
type: 'RadialTree',
root: 'parent'
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Note: To use radial tree layout functionality, inject the RadialTree module in the diagram component.