Data binding in Angular TreeGrid component
25 Sep 202524 minutes to read
The TreeGrid supports flexible data binding options, allowing integration with both local object arrays and remote RESTful JSON data services. Assign the dataSource property with either a JavaScript object array or a DataManager instance.
TreeGrid provides two primary data binding methods:
- Local data
- Remote data
To learn how to bind both local and remote data to the TreeGrid, watch this video:
Binding with Ajax
You can use TreeGrid dataSource property to bind the data source to TreeGrid from external fetch request. The following code demonstrates fetching the data source from the server using a fetch request and binding it to the dataSource property through the onSuccess event.
import { NgModule,ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { PageService, SortService, FilterService } from '@syncfusion/ej2-angular-treegrid'
import {ButtonModule} from '@syncfusion/ej2-angular-buttons'
import { Component, OnInit } from '@angular/core';
import { Fetch } from '@syncfusion/ej2-base';
import { TreeGridComponent } from '@syncfusion/ej2-angular-treegrid';
import { DataManager } from '@syncfusion/ej2-data';
@Component({
imports: [
TreeGridModule,
ButtonModule
],
providers: [PageService,
SortService,
FilterService],
standalone: true,
selector: 'app-container',
template: ` <button ejs-button (click)="click()">Bind Data</button>
<ejs-treegrid #treegrid [dataSource]='data' [treeColumnIndex]='1' parentIdMapping='ParentItem' idMapping='TaskID' [allowPaging]="true" height=240>
<e-columns>
<e-column field='TaskID' headerText='Task ID' width='90' textAlign='Right'></e-column>
<e-column field='TaskName' headerText='Task Name' width='170'></e-column>
<e-column field='StartDate' headerText='Start Date' width='130' format="yMd" textAlign='Right'></e-column>
<e-column field='Duration' headerText='Duration' width='80' textAlign='Right'></e-column>
</e-columns>
</ejs-treegrid>`
})
export class AppComponent implements OnInit {
public data?: DataManager;
@ViewChild('treegrid')
public treegrid?: TreeGridComponent;
ngOnInit(): void {
}
click(): any{
let fetch = new Fetch("https://services.syncfusion.com/angular/production/api/SelfReferenceData","GET");
let trgrid = this.treegrid;
fetch.send();
fetch.onSuccess = function (data: string) {
(trgrid as TreeGridComponent).hideSpinner();
(trgrid as TreeGridComponent).dataSource = data;
};
}
}/**
* TreeGrid DataSource
*/
export let sampleData: Object[] = [
{
taskID: 1,
taskName: 'Planning',
startDate: new Date('02/03/2017'),
endDate: new Date('02/07/2017'),
progress: 100,
duration: 5,
priority: 'Normal',
approved: false,
subtasks: [
{ taskID: 2, taskName: 'Plan timeline', startDate: new Date('02/03/2017'),
endDate: new Date('02/07/2017'), duration: 5, progress: 100, priority: 'Normal', approved: false },
{ taskID: 3, taskName: 'Plan budget', startDate: new Date('02/03/2017'),
endDate: new Date('02/07/2017'), duration: 5, progress: 100, priority: 'Low', approved: true },
{ taskID: 4, taskName: 'Allocate resources', startDate: new Date('02/03/2017'),
endDate: new Date('02/07/2017'), duration: 5, progress: 100, priority: 'Critical', approved: false },
{ taskID: 5, taskName: 'Planning complete', startDate: new Date('02/07/2017'),
endDate: new Date('02/07/2017'), duration: 0, progress: 0, priority: 'Low', approved: true }
]
},
{
taskID: 6,
taskName: 'Design',
startDate: new Date('02/10/2017'),
endDate: new Date('02/14/2017'),
duration: 3,
progress: 86,
priority: 'High',
approved: false,
subtasks: [
{ taskID: 7, taskName: 'Software Specification', startDate: new Date('02/10/2017'),
endDate: new Date('02/12/2017'), duration: 3, progress: 60, priority: 'Normal', approved: false },
{ taskID: 8, taskName: 'Develop prototype', startDate: new Date('02/10/2017'),
endDate: new Date('02/12/2017'), duration: 3, progress: 100, priority: 'Critical', approved: false },
{ taskID: 9, taskName: 'Get approval from customer', startDate: new Date('02/13/2017'),
endDate: new Date('02/14/2017'), duration: 2, progress: 100, priority: 'Low', approved: true },
{ taskID: 10, taskName: 'Design Documentation', startDate: new Date('02/13/2017'),
endDate: new Date('02/14/2017'), duration: 2, progress: 100, priority: 'High', approved: true },
{ taskID: 11, taskName: 'Design complete', startDate: new Date('02/14/2017'),
endDate: new Date('02/14/2017'), duration: 0, progress: 0, priority: 'Normal', approved: true }
]
},
{
taskID: 12,
taskName: 'Implementation Phase',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'Normal',
approved: false,
duration: 11,
progress: 66,
subtasks: [
{
taskID: 13,
taskName: 'Phase 1',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'High',
approved: false,
progress: 50,
duration: 11,
subtasks: [{
taskID: 14,
taskName: 'Implementation Module 1',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'Normal',
duration: 11,
progress: 10,
approved: false,
subtasks: [
{ taskID: 15, taskName: 'Development Task 1', startDate: new Date('02/17/2017'),
endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'High', approved: false },
{ taskID: 16, taskName: 'Development Task 2', startDate: new Date('02/17/2017'),
endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'Low', approved: true },
{ taskID: 17, taskName: 'Testing', startDate: new Date('02/20/2017'),
endDate: new Date('02/21/2017'), duration: 2, progress: '0', priority: 'Normal', approved: true },
{ taskID: 18, taskName: 'Bug fix', startDate: new Date('02/24/2017'),
endDate: new Date('02/25/2017'), duration: 2, progress: '0', priority: 'Critical', approved: false },
{ taskID: 19, taskName: 'Customer review meeting', startDate: new Date('02/26/2017'),
endDate: new Date('02/27/2017'), duration: 2, progress: '0', priority: 'High', approved: false },
{ taskID: 20, taskName: 'Phase 1 complete', startDate: new Date('02/27/2017'),
endDate: new Date('02/27/2017'), duration: 0, progress: '50', priority: 'Low', approved: true }
]
}]
},
{
taskID: 21,
taskName: 'Phase 2',
startDate: new Date('02/17/2017'),
endDate: new Date('02/28/2017'),
priority: 'High',
approved: false,
duration: 12,
progress: 60,
subtasks: [{
taskID: 22,
taskName: 'Implementation Module 2',
startDate: new Date('02/17/2017'),
endDate: new Date('02/28/2017'),
priority: 'Critical',
approved: false,
duration: 12,
progress: 90,
subtasks: [
{ taskID: 23, taskName: 'Development Task 1', startDate: new Date('02/17/2017'),
endDate: new Date('02/20/2017'), duration: 4, progress: '50', priority: 'Normal', approved: true },
{ taskID: 24, taskName: 'Development Task 2', startDate: new Date('02/17/2017'),
endDate: new Date('02/20/2017'), duration: 4, progress: '50', priority: 'Critical', approved: true },
{ taskID: 25, taskName: 'Testing', startDate: new Date('02/21/2017'),
endDate: new Date('02/24/2017'), duration: 2, progress: '0', priority: 'High', approved: false },
{ taskID: 26, taskName: 'Bug fix', startDate: new Date('02/25/2017'),
endDate: new Date('02/26/2017'), duration: 2, progress: '0', priority: 'Low', approved: false },
{ taskID: 27, taskName: 'Customer review meeting', startDate: new Date('02/27/2017'),
endDate: new Date('02/28/2017'), duration: 2, progress: '0', priority: 'Critical', approved: true },
{ taskID: 28, taskName: 'Phase 2 complete', startDate: new Date('02/28/2017'),
endDate: new Date('02/28/2017'), duration: 0, progress: '50', priority: 'Normal', approved: false }
]
}]
},
{
taskID: 29,
taskName: 'Phase 3',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'Normal',
approved: false,
duration: 11,
progress: 30,
subtasks: [{
taskID: 30,
taskName: 'Implementation Module 3',
startDate: new Date('02/17/2017'),
endDate: new Date('02/27/2017'),
priority: 'High',
approved: false,
duration: 11,
progress: 60,
subtasks: [
{ taskID: 31, taskName: 'Development Task 1', startDate: new Date('02/17/2017'),
endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'Low', approved: true },
{ taskID: 32, taskName: 'Development Task 2', startDate: new Date('02/17/2017'),
endDate: new Date('02/19/2017'), duration: 3, progress: '50', priority: 'Normal', approved: false },
{ taskID: 33, taskName: 'Testing', startDate: new Date('02/20/2017'),
endDate: new Date('02/21/2017'), duration: 2, progress: '0', priority: 'Critical', approved: true },
{ taskID: 34, taskName: 'Bug fix', startDate: new Date('02/24/2017'),
endDate: new Date('02/25/2017'), duration: 2, progress: '0', priority: 'High', approved: false },
{ taskID: 35, taskName: 'Customer review meeting', startDate: new Date('02/26/2017'),
endDate: new Date('02/27/2017'), duration: 2, progress: '0', priority: 'Normal', approved: true },
{ taskID: 36, taskName: 'Phase 3 complete', startDate: new Date('02/27/2017'),
endDate: new Date('02/27/2017'), duration: 0, progress: '50', priority: 'Critical', approved: false },
]
}]
}
]
}
];import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
- When binding data in this manner, the dataSource is treated as local data, and CRUD operations cannot be performed on the server end.
Handling expandStateMapping
To control the expanded or collapsed state of parent rows, assign the expandStateMapping property to the field in your data source that indicates the expansion state.
The expandStateMapping property should map to a boolean field (e.g., true for expanded, false for collapsed) in your data source, enabling the TreeGrid to render parent records in the appropriate state based on data values.
import { Component, OnInit } from '@angular/core';
import { DataManager, UrlAdaptor } from '@syncfusion/ej2-data';
import './App.css';
@Component({
selector: 'app-container',
template: `<ejs-treegrid [dataSource]='data' [treeColumnIndex]='1' height='400' hasChildMapping='isParent', idMapping='TaskID' expandStateMapping='IsExpanded' parentIdMapping='ParentValue'>
<e-columns>
<e-column field='TaskID' headerText='Task ID' width='90' textAlign='Right'></e-column>
<e-column field='TaskName' headerText='Task Name' width='180'></e-column>
<e-column field='Duration' headerText='Duration' width='80' textAlign='Right'></e-column>
</e-columns>
</ejs-treegrid>`
})
export class AppComponent implements OnInit {
public data: DataManager;
public dataManager: DataManager = new DataManager({
adaptor: new UrlAdaptor,
url: "Home/DataSource",
});
ngOnInit(): void {
this.data = this.dataManager;
}
}The following code example defines expandStateMapping property at server end.
public ActionResult ExpandStateMapping()
{
return View();
}
public class TreeData
{
public static List<TreeData> tree = new List<TreeData>();
[System.ComponentModel.DataAnnotations.Key]
public int TaskID { get; set; }
public string TaskName { get; set; }
public int Duration { get; set; }
public int? ParentValue { get; set; }
public bool? isParent { get; set; }
public bool IsExpanded { get; set; }
public TreeData() { }
public static List<TreeData> GetTree()
{
if (tree.Count == 0)
{
int root = 0;
for (var t = 1; t <= 500; t++)
{
Random ran = new Random();
string math = (ran.Next() % 3) == 0 ? "High" : (ran.Next() % 2) == 0 ? "Release Breaker" : "Critical";
string progr = (ran.Next() % 3) == 0 ? "Started" : (ran.Next() % 2) == 0 ? "Open" : "In Progress";
root++;
int rootItem = root;
tree.Add(new TreeData() { TaskID = rootItem, TaskName = "Parent task " + rootItem.ToString(), isParent = true, IsExpanded = false, ParentValue = null, Duration = ran.Next(1, 50) });
int parent = root;
for (var d = 0; d < 1; d++)
{
root++;
string value = ((parent + 1) % 3 == 0) ? "Low" : "Critical";
int par = parent + 1;
progr = (ran.Next() % 3) == 0 ? "In Progress" : (ran.Next() % 2) == 0 ? "Open" : "Validated";
int iD = root;
tree.Add(new TreeData() { TaskID = iD, TaskName = "Child task " + iD.ToString(), isParent = true, IsExpanded = false, ParentValue = rootItem, Duration = ran.Next(1, 50) });
int subparent = root;
for (var c = 0; c < 500; c++)
{
root++;
string val = ((subparent + c + 1) % 3 == 0) ? "Low" : "Critical";
int subchild = subparent + c + 1;
string progress = (ran.Next() % 3) == 0 ? "In Progress" : (ran.Next() % 2) == 0 ? "Open" : "Validated";
int childID = root ;
tree.Add(new TreeData() { TaskID = childID, TaskName = "sub Child task " + childID.ToString(), isParent = false, IsExpanded = false, ParentValue = subparent, Duration = ran.Next(1, 50) });
}
}
}
}
return tree;
}
}Refresh the datasource
Refreshing the datasource in a Syncfusion TreeGrid involves updating the data that the TreeGrid displays dynamically. This operation is essential when you need to reflect changes in the underlying data without reloading the entire page or component.
You can add/delete the datasource records through an external button. To reflect these changes in the TreeGrid, you must assign the modified data to the dataSource property.
Steps to refresh the TreeGrid after datasource change:
Step 1: Modify the datasource
You can add or delete records from the datasource using the following code:
const dataSource: object = extendArray((this.treegridObj as TreeGridComponent).dataSource as object[]);
// Added a new record.
(dataSource as object[]).unshift({ TaskID: 99, TaskName: "New Data", StartDate: new Date('02/03/2017'), Duration: 10 });
// Delete a record.
(dataSource as object[]).splice(selectedRowIndex, 1);Step 2: Refresh the TreeGrid
Refresh the TreeGrid after the datasource change by assign the modified data to dataSource property.
(this.treegridObj as TreeGridComponent).dataSource = dataSource; // Refresh the TreeGrid.The following example demonstrates how to add and delete records from datasource using an external button:
import { NgModule,ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { PageService, SortService, FilterService } from '@syncfusion/ej2-angular-treegrid'
import {ButtonModule} from '@syncfusion/ej2-angular-buttons'
import { DropDownListAllModule } from '@syncfusion/ej2-angular-dropdowns'
import { Component, OnInit, ViewChild } from '@angular/core';
import { projectData } from './datasource';
import { TreeGridComponent , extendArray } from '@syncfusion/ej2-angular-treegrid';
import { ButtonComponent } from '@syncfusion/ej2-angular-buttons';
@Component({
imports: [
TreeGridModule,
ButtonModule,
DropDownListAllModule
],
providers: [PageService,
SortService,
FilterService],
standalone: true,
selector: 'app-container',
template: `<button #btn1 ejs-button cssClass="e-flat" (click)="add()">Add</button>
<button #btn2 ejs-button cssClass="e-flat" (click)="delete()">Delete</button>
<ejs-treegrid #treegridObj [dataSource]='data' idMapping='TaskID' parentIdMapping='parentID' [treeColumnIndex]='1'[height]='280'>
<e-columns>
<e-column field='TaskID' headerText='Task ID' width='70' textAlign='Right'></e-column>
<e-column field='TaskName' headerText='Task Name' width='100'></e-column>
<e-column field='StartDate' headerText='Start Date' width='90' format="yMd" textAlign='Right'></e-column>
<e-column field='EndDate' headerText='End Date' width='90' format="yMd" textAlign='Right'></e-column>
<e-column field='Duration' headerText='Duration' width='90' textAlign='Right'></e-column>
<e-column field='Priority' headerText='Priority' width='90'></e-column>
</e-columns>
</ejs-treegrid>`,
})
export class AppComponent implements OnInit {
public data?: Object[];
@ViewChild('treegridObj')
public treegridObj?: TreeGridComponent;
ngOnInit(): void {
this.data = projectData;
}
add() {
const dataSource = extendArray((this.treegridObj as TreeGridComponent).dataSource as object[]);
(dataSource as object[]).unshift({ TaskID: 99, TaskName: "New Data", StartDate: new Date('02/03/2017'), EndDate: new Date('04/04/2017'), Duration: 10, Priority: "High" }); // Add record.
(this.treegridObj as TreeGridComponent).dataSource = dataSource; // Refresh the TreeGrid.
}
delete() {
const selectedRow = (this.treegridObj as TreeGridComponent).getSelectedRowIndexes().length;
const selectedRowIndex = (this.treegridObj as TreeGridComponent).getSelectedRowIndexes()[0];
const dataSource = extendArray((this.treegridObj as TreeGridComponent).dataSource as object[]);
if (selectedRow > 0) {
(dataSource as object[]).splice(selectedRowIndex, 1); // Delete record.
}
else {
alert("No records selected for delete operation");
}
(this.treegridObj as TreeGridComponent).dataSource = dataSource; // Refresh the TreeGrid.
}
}import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));For further details, visit the
Angular TreeGrid feature tourto explore its advanced capabilities. Additionally, explore theAngular TreeGrid exampleto see data presentation and manipulation in action.