Column Rendering

25 Aug 202524 minutes to read

In the Syncfusion® Angular TreeGrid, column rendering provides the ability to precisely control how data is presented. This allows manual column definition, automatic column generation, and dynamic customization of data presentation. With column rendering, data can be displayed exactly as needed, offering extensive possibilities for organizing and showcasing information within the TreeGrid.

The column definitions serve as the data source schema in the TreeGrid. TreeGrid operations, such as sorting and filtering, are performed based on column definitions. The field property of the TreeGrid column is necessary to map the data source values in the TreeGrid columns.

  1. If the column field is not specified in the dataSource, the column values will be empty.
  2. If the field name contains dot operator, it is considered as complex binding.
  3. The field property must be defined for a template column to perform CRUD or data operations such as filtering and searching.

Define columns manually

To define columns manually in the TreeGrid, use the e-columns element to define the columns and represent each column with its respective properties such as field, headerText, type, and width set accordingly. This allows customization of the column’s behavior and appearance based on requirements.

The following example demonstrates how to define columns manually in the TreeGrid:

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 { Component, OnInit } from '@angular/core';
import { sampleData } from './datasource';
import { ButtonComponent } from '@syncfusion/ej2-angular-buttons';
import { TreeGridComponent, ReorderService } from '@syncfusion/ej2-angular-treegrid';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' height='285' [treeColumnIndex]='1' childMapping='subtasks'>
                 <e-columns>
                    <e-column field='taskID' headerText='Task ID' textAlign='Right' width=90></e-column>
                    <e-column field='taskName' headerText='Task Name' textAlign='Left' width=180></e-column>
                    <e-column field='startDate' headerText='Start Date' textAlign='Right' format='yMd' width=90></e-column>
                    <e-column field='duration' headerText='Duration' textAlign='Right' width=80></e-column>
                    <e-column field='progress' headerText='Progress' textAlign='Right' width=120></e-column>
                 </e-columns>
               </ejs-treegrid>`,

})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = sampleData;
    }

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Auto generated columns

The TreeGrid automatically generates columns when the column declaration is empty or undefined while initializing the TreeGrid. All columns in the dataSource are bound as TreeGrid columns.

The following example demonstrates auto-generated columns in the TreeGrid:

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 { Component, OnInit } from '@angular/core';
import { sampleData } from './datasource';

@Component({
    imports: [TreeGridModule,],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks'>
                </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = sampleData;
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

  • When columns are auto-generated, the column type is determined from the first record of the dataSource.
  • For large datasets, auto-generating columns can result in performance issues. In such cases, it is recommended to specify columns manually in the columns property during initialization or use column virtualization by setting enableColumnVirtualization property to true.

Set Primary Key for auto generated columns when editing is enabled

When editing is enabled in the TreeGrid, a primary key must be set for auto-generated columns to uniquely identify each row for operations such as updating or deleting data. This can be achieved using the isPrimaryKey property of the column object through the dataBound event.

By setting isPrimaryKey to true for an auto-generated column in the Syncfusion® TreeGrid, it can be specified as the primary key column, which uniquely identifies each row when editing is enabled.

The following example demonstrates how to set a primary key for an auto-generated column when editing is enabled:

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { PageService, SortService, FilterService, EditService } from '@syncfusion/ej2-angular-treegrid'
import { Component, OnInit, ViewChild } from '@angular/core';
import { sampleData } from './datasource';
import { TreeGridComponent, EditSettingsModel, Column, } from '@syncfusion/ej2-angular-treegrid';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService, EditService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' 
                     allowPaging='true' [editSettings]='editSettings' (dataBound)="dataBound()">
                </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];
    public editSettings: EditSettingsModel | undefined;

    @ViewChild('treegrid')
    public treegrid?: TreeGridComponent;

    ngOnInit(): void {
        this.data = sampleData;
        this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true };
    }
    dataBound() {
        (((this.treegrid as TreeGridComponent).columns[0]) as Column).isPrimaryKey = true;
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

If the column field name is known, the getColumnByField method can be used to retrieve the column object. Then, the isPrimaryKey property can be set to true for that column, as demonstrated below:

onDataBound(event: any): void {
    const column: ColumnModel = this.treegrid.getColumnByField('taskID');
    column.isPrimaryKey = true;
  }

Set column options to auto generated columns

To configure column options such as type, format and width for auto-generated columns in the Syncfusion® TreeGrid, use the dataBound event of the TreeGrid component. This event is triggered after the data has been bound to the TreeGrid. By handling this event, the desired column options can be specified for the auto-generated columns.

The following example demonstrates how to set column options for auto-generated columns using the dataBound event:

In the following example, width is set for taskID column, date type is set for startDate and endDate columns, and format is set for duration, startDate and endDate columns.

import { NgModule, ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { SortService, FilterService } from '@syncfusion/ej2-angular-treegrid'
import { Component, OnInit } from '@angular/core';
import { sampleData } from './datasource';
import { TreeGridComponent, EditSettingsModel, EditService, Column, PageService } from '@syncfusion/ej2-angular-treegrid';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' 
                 (dataBound)="dataBound()">
                </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];
    @ViewChild('treegrid')
    public treegrid?: TreeGridComponent;

    ngOnInit(): void {
        this.data = sampleData;
    }
    dataBound() {
        for (const cols of (this.treegrid as TreeGridComponent).columns) {
            if ((cols as Column).field === 'taskID') {
                (cols as Column).width = 120;
            }
            if ((cols as Column).field === 'startDate') {
                (cols as Column).type = 'date';
                (cols as Column).format = 'yMd';
            }
            if ((cols as Column).field === 'endDate') {
                (cols as Column).type = 'date';
                (cols as Column).format = 'yMd';
            }
            if ((cols as Column).field === 'duration') {
                (cols as Column).format = 'P2';
            }
        }
        (this.treegrid as TreeGridComponent).refreshColumns();
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Dynamic column generation

The Syncfusion® TreeGrid component allows dynamic generation of columns at runtime, based on the provided data. This feature is useful when displaying data with varying columns based on user requirements or dynamic data sources.

Using ngFor directive

To create dynamically generated columns in the Syncfusion® TreeGrid component using the ngFor directive, first define an array of column objects in the component.ts file. Each column object should include a field and headerText property, which will be used to bind the corresponding properties of the e-column component.

The following example demonstrates dynamic column generation in the TreeGrid using the ngFor directive:

import { NgModule, ViewChild } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { CommonModule } from '@angular/common';
import { TreeGridModule } from '@syncfusion/ej2-angular-treegrid'
import { PageService, SortService, FilterService } from '@syncfusion/ej2-angular-treegrid'
import { Component, NgIterable, OnInit, } from '@angular/core';
import { sampleData } from './datasource';
import { ColumnModel } from '@syncfusion/ej2-angular-treegrid';
@Component({
    imports: [TreeGridModule, CommonModule],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks'>
                    <e-columns>
                         <e-column *ngFor="let column of columns" [field]="column.field" [headerText]="column.headerText"></e-column> 
                     </e-columns>
                </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];
    public columns?: NgIterable<ColumnModel> | null | undefined;

    ngOnInit(): void {
        this.data = sampleData;
        this.columns = [
            { field: 'taskID', headerText: 'Task ID', width: 90, textAlign: 'Right' },
            { field: 'taskName', headerText: 'Task Name', width: 180 },
            { field: 'startDate', headerText: 'Start Date', width: 90, textAlign: 'Right', type: 'date', format: 'yMd' },
            { field: 'duration', headerText: 'Duration', width: 80, textAlign: 'Right' }
        ];
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Using valueAccessor property

Dynamic column generation using value accessor allows accessing and manipulating the display data values in a TreeGrid column. By using the valueAccessor property of a TreeGrid column, the display value of the column can be customized based on the data.

To use the valueAccessor property, define the column with the property and provide a function that will return the formatted value. The function receives two arguments:

  • field: represents the data field of the column.
  • data: represents the data record for the corresponding row.

In the following example, the currencyFormatter function takes the price value of the data object, appends the Euro symbol to it, and returns the formatted string. The orderFormatter function concatenates the orderName and Category values of the data object and returns the combined string.

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 { Component, OnInit, } from '@angular/core';
import { formatData } from './datasource';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' >
                    <e-columns>
                          <e-column field='orderID' headerText='Order ID' textAlign='Right' width=90></e-column>
                          <e-column field='orderName' headerText='Order Name' [valueAccessor]='orderFormatter' textAlign='Left' width=180></e-column>
                          <e-column field='orderDate' headerText='Order Date' textAlign='Right'  width=160 format='yMd'></e-column>
                          <e-column field='price' headerText='Price' textAlign='Right' [valueAccessor]='currencyFormatter'  width=80></e-column>
                    </e-columns>
             </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = formatData;
    }
    currencyFormatter(field: string, data: Object | any, column: Object): string {
        return '€' + data['price'];
    }

    orderFormatter(field: string, data: Object | any, column: Object): string {
        return data[field] + '-' + data['Category'];
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

The valueAccessor function can have performance implications if used to access a large number of data records or perform complex data manipulations. To avoid performance issues, enable the virtualization feature while using the valueAccessor property. This ensures that only the visible rows are rendered, resulting in faster rendering times.

Display array type columns

The TreeGrid component allows easy binding of an array of objects to a column using the valueAccessor property. This property allows customization of how the data is displayed in the column.

For example, consider a column named Name that contains an array of two objects, FirstName and LastName. The valueAccessor property can be used to join these two objects and bind them to the column.

This displays the concatenated value of FirstName and LastName in the Name column of the TreeGrid. The following example demonstrates how this can be achieved:

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 { Component, OnInit, } from '@angular/core';
import { stringData } from './datasource';
@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' >
                    <e-columns>
                        <e-column field='taskID' headerText='Task ID' textAlign='Right' width=90></e-column>
                        <e-column field='taskName' headerText='Task Name' textAlign='Left' width=180></e-column>
                        <e-column field='name' headerText='Full Name' textAlign='Right' [valueAccessor]='orderFormatter' width=90></e-column>
                        <e-column field='duration' headerText='Duration' textAlign='Right' width=80></e-column>
                    </e-columns>
            </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = stringData;
    }
    orderFormatter(field: string, data: Object | any, column: Object): string {
        return data[field].map(function (s: { lastName: string, firstName: string }): string {
            return s.lastName || s.firstName
        }).join(' ');
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Since customized values are displayed in the Name column, data operations such as sorting and filtering cannot be performed for this column.

Expression column

An expression column can be achieved in the TreeGrid by using the valueAccessor property. The valueAccessor property allows definition of a function that calculates the value for the expression column based on the values of other columns.

In this example, the TreeGrid has columns orderID, orderName, units, and unitprice. An expression column called Total price is added that calculates the total prices for each row based on the values of units and unitprice columns.

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 { Component, OnInit } from '@angular/core';
import { formatData } from './datasource';
@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' >
                    <e-columns>
                        <e-column field='orderID' headerText='Order ID' textAlign='Right' width=90></e-column>
                        <e-column field='orderName' headerText='Order Name' textAlign='Left' width=180></e-column>
                        <e-column field='units' headerText='Units' width=120 textAlign='Right'></e-column>
                        <e-column field='unitPrice' headerText='Unit Price' width=120 textAlign='Right'></e-column>
                        <e-column headerText='Total Price' [valueAccessor]='totalPrice' width=120 format='c2' type='number' textAlign='Right'></e-column>
                    </e-columns>
              </ejs-treegrid>`,
})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = formatData;
    }

    totalPrice(field: string, data: { units: number, unitprice: number } | any, column: Object): number {
        return data.units * data.unitPrice;
    };
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Since customized values are displayed in the Total Price column, data operations such as sorting and filtering cannot be performed for this column.

Display serial number

To display serial numbers in the TreeGrid for every row, the rowDataBound event can be used. The rowDataBound event is triggered for each row in the TreeGrid when the data is bound to the TreeGrid.

Within the event handler, the pagesize and currentPage index can be obtained from the TreeGrid’s pageSettings property. Using these values, the serial number can be calculated based on the page size, current page, and row index. Finally, the calculated serial number can be set as the innerHTML of the corresponding row cell.

The following example demonstrates how to display serial numbers in a TreeGrid using the rowDataBound 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 { Component, OnInit } from '@angular/core';
import { projectData } from './datasource';
import { PageSettingsModel, TreeGridComponent } from '@syncfusion/ej2-angular-treegrid';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid #treegrid [dataSource]='data' [treeColumnIndex]='1' parentIdMapping='parentID' idMapping='TaskID' height=265 allowPaging="true" [pageSettings]="pageSettings" (rowDataBound)='rowDataBound($event)'>
                    <e-columns> 
                        <e-column field='S.No' textAlign='Center' width=120></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?: Object[];
    @ViewChild('treegrid')
    public treegrid?: TreeGridComponent;
    public pageSettings?: PageSettingsModel;

    ngOnInit(): void {
        this.data = projectData;
        this.pageSettings = { pageSize: 8 };
    }
    rowDataBound({ row }: any) {
        if (row) {
            var rowIndex = parseInt(row.getAttribute('aria-rowIndex') as string);
            var currentPageNumber = (this.treegrid as TreeGridComponent).grid
                .pageSettings.currentPage;
            var pageSize = (this.treegrid as TreeGridComponent).pageSettings.pageSize;
            var startIndex =
                ((currentPageNumber as number) - 1) * (pageSize as number);
            (row.querySelector('.e-rowcell') as Element).innerHTML = (
                startIndex + rowIndex
            ).toString();
        }
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Since customized values are displayed in the S.No column, data operations such as sorting and filtering cannot be performed for this column.

Complex data binding

The Syncfusion® TreeGrid component allows complex data binding by using the dot (.) operator in the column.field. This feature is particularly useful when dealing with nested or complex data structures.

Using local data

To enable complex data binding in the TreeGrid component using local data, use the dot (.) operator in the field property of the column. The following example demonstrates how to achieve complex data binding using local data:

In the following example, the nested Task object’s firstName and lastName properties are bound using the dot (.) operator.

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 { Component, OnInit } from '@angular/core';
import { complexData } from './datasource';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' >
                    <e-columns>
                        <e-column field='taskID' headerText='Task ID' textAlign='Right' width=90></e-column>
                        <e-column field='taskName' headerText='Task Name' textAlign='Left' width=180></e-column>
                        <e-column field='assignee.firstName' headerText='Assignee' textAlign='Right' width=90></e-column>
                        <e-column field='duration' headerText='Duration' textAlign='Right' width=80></e-column>
                    </e-columns>
            </ejs-treegrid>`
})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = complexData;
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Since customized values are displayed in the column, data operations such as sorting and filtering cannot be performed for this column.

Using remote data

To enable complex data binding in the TreeGrid component using remote data, add the expand query to the query property of the TreeGrid to eager load the complex data. The following example demonstrates how to achieve complex data binding using remote data:

In the following example, the expand query is used to load the nested Tasks object’s Name property using the dot (.) operator.

import { Component } from '@angular/core';
import { DataManager, Query, UrlAdaptor } from '@syncfusion/ej2-data';

@Component({
  selector: 'app-root',
  template: `
  <ejs-treegrid [dataSource]='data' [query]="query" [treeColumnIndex]='1' height='400' idMapping='TaskID' parentIdMapping='ParentValue' hasChildMapping='isParent' [allowPaging]="true" [pageSettings]="pagesettings" >
                <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-column field='Tasks.Name' headerText='Name' width='100' textAlign='Right'></e-column>
                  </e-columns>
               </ejs-treegrid>
 `,

})
export class AppComponent {
  public data: DataManager = new DataManager({
    adaptor: new UrlAdaptor,
    url: "Home/Datasource",
  });
  public query?: Query = new Query().expand('Tasks');
  public pagesettings = { pageSize: 12, pageSizeMode: 'Root' };
}

The following code example describes handling of server end:

public ActionResult DataSource(DataManagerRequest dm)
{
    List<TreeData> data = new List<TreeData>();
    data = TreeData.GetTree();
    DataOperations operation = new DataOperations();
    IEnumerable<TreeData> DataSource = data;
    
    if (!(dm.Where != null && dm.Where.Count > 1))
    {
        data = data.Where(p => p.ParentValue == null).ToList();
    }
    DataSource = data;
    if (dm.Search != null && dm.Search.Count > 0) // Searching
    {
        DataSource = operation.PerformSearching(DataSource, dm.Search);
    }
    if (dm.Sorted != null && dm.Sorted.Count > 0 && dm.Sorted[0].Name != null) // Sorting
    {
        DataSource = operation.PerformSorting(DataSource, dm.Sorted);
    }
    if (dm.Where != null && dm.Where.Count > 1) //filtering
    {
        DataSource = operation.PerformFiltering(DataSource, dm.Where, "and");
    }
    int count = data.Count;
    DataSource = data;
    if (dm.Skip != 0)
    {
        DataSource = operation.PerformSkip(DataSource, dm.Skip);   //Paging
    }
    if (dm.Take != 0)
    {
        DataSource = operation.PerformTake(DataSource, dm.Take);
    }
    return dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource);

}

View the complex data binding with remote data sample on GitHub

Complex data binding with list of array of objects

The Syncfusion® TreeGrid component supports complex data binding with lists of arrays of objects. This feature allows binding complex data with multiple levels of nested objects and arrays to the TreeGrid.

The following example demonstrates how to set complex field for datasource having array of objects:

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 { Component, OnInit } from '@angular/core';
import { complexData } from './datasource';

@Component({
    imports: [TreeGridModule,],
    providers: [PageService, SortService, FilterService],
    standalone: true,
    selector: 'app-container',
    template: `<ejs-treegrid [dataSource]='data' height='250' [treeColumnIndex]='1' childMapping='subtasks' >
                    <e-columns>
                        <e-column field='taskID' headerText='Task ID' textAlign='Right' width=90></e-column>
                        <e-column field='taskName' headerText='Task Name' textAlign='Left' width=180></e-column>
                        <e-column field='assignee.0.firstName' headerText='Assignee' textAlign='Right' width=90></e-column>
                        <e-column field='duration' headerText='Duration' textAlign='Right' width=80></e-column>
                    </e-columns>
            </ejs-treegrid>`
})
export class AppComponent implements OnInit {

    public data?: Object[];

    ngOnInit(): void {
        this.data = complexData;
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Since customized values are displayed in the column, data operations such as sorting and filtering cannot be performed for this column.