Column rendering in Angular Gantt component

5 Apr 202524 minutes to read

In Syncfusion® Angular Gantt chart, column rendering provides you with the ability to finely control how data is presented. This allows you to manually define columns, automatically generate them, and dynamically customize data presentation. With column rendering, you can ensure that your data is displayed exactly as needed, offering a wide range of possibilities for organizing and showcasing information within the gantt chart.

The column definitions are used as the data source schema in the gantt chart. The gantt operations such as sorting, filtering are performed based on column definitions. The field property of gantt chart column is necessary to map the datasource values in the gantt chart 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. It is must to define the field property for a template column, to perform CRUD or data operations such as filtering, searching etc.

Define columns manually

To define columns manually in gantt chart, you can use the e-columns to define the columns and represent each column with its respective properties such as field, headerText and width set accordingly. This allows you to customize the column’s behavior and appearance based on the requirements.

Here’s an example code snippet that demonstrates how to define columns manually in the Syncfusion® Angular Gantt chart:

import { BrowserModule } from '@angular/platform-browser';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';

import { Component, ViewEncapsulation, ViewChild, OnInit, NgModule } from '@angular/core';
import { GanttComponent, } from '@syncfusion/ej2-angular-gantt';
import { GanttData } from './data';

@Component({
    imports: [
         GanttModule
    ],
standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" #gantt height="430px"  [dataSource]="data"  [taskFields]="taskSettings" [treeColumnIndex]='1' [splitterSettings] = "splitterSettings"> 
            <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=290></e-column>
                <e-column field='StartDate' headerText='Start Date' textAlign='Right' width=120 ></e-column>
                <e-column field='Duration' headerText='Duration' textAlign='Right' width=90 ></e-column>
                <e-column field='Progress' headerText='Progress' textAlign='Right' width=120></e-column>
            </e-columns>
       </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    // Data for Gantt
    public data?: object[];
    @ViewChild('gantt')
    public gantt?: GanttComponent;
    public taskSettings?: object;
    public splitterSettings?: object;
    public ngOnInit(): void {
        this.data = GanttData;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
        this.splitterSettings = {
            position: '75%'
        };
    }
}
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® Gantt chart component allows you to dynamically generate columns at runtime, based on the data provided. This feature is useful when you need to display data with varying columns based on user requirements or dynamic data sources.

Using ngFor directive

To create dynamically generated columns in the Syncfusion® Gantt chart component using the ngFor directive, you will first need to define an array of column objects in your 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.

Here is an example for dynamically generate columns in the gantt chart using ngFor directive:

import { BrowserModule } from '@angular/platform-browser';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';
import { SelectionService  } from '@syncfusion/ej2-angular-gantt';

import { Component, ViewEncapsulation, OnInit, ViewChild, NgIterable, NgModule } from '@angular/core';
import { GanttComponent, ColumnModel } from '@syncfusion/ej2-angular-gantt';
import { GanttData } from './data';

@Component({
    imports: [
         GanttModule
    ],
providers: [SelectionService],
standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" #gantt height="430px"  [dataSource]="data"
        [taskFields]="taskSettings" [treeColumnIndex]='1' [columns]="columns"  [splitterSettings] = "splitterSettings">   
        <e-columns>
            <e-column *ngFor="let column of columns" [field]="column.field" [headerText]="column.headerText" [width]=240></e-column> 
        </e-columns>   
       </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    // Data for Gantt
    public data?: object[];
    @ViewChild('gantt')
    public gantt?: GanttComponent;
    public taskSettings?: object;
    public columns?: NgIterable<ColumnModel> | null | undefined;
    public splitterSettings?: object;
    public ngOnInit(): void {
        this.data = GanttData;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
        this.columns = [
            { field: 'TaskID', headerText: 'Task ID' },
            { field: 'TaskName', headerText: 'Task Name' },
            { field: 'StartDate', headerText: 'Start Date' },
            { field: 'Duration', headerText: 'Duration' },
            { field: 'Progress', headerText: 'Progress' }
        ];
        this.splitterSettings = {
            position: '75%'
        };
    }
}
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 you to access and manipulate the display data values in a gantt chart column. By using the valueAccessor property of a gantt chart column, you can customize the display value of the column based on the data.

To use 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 provided code, the percentageFormatter function takes the progress value of the data object, appends the percentage sign to it, and returns the formatted string. The concatenateFields function concatenates the TaskName and TaskID values of the data object and returns the combined string.

import { BrowserModule } from '@angular/platform-browser';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';

import { Component, ViewEncapsulation, ViewChild, OnInit, NgModule } from '@angular/core';
import { GanttComponent } from '@syncfusion/ej2-angular-gantt';
import { GanttData } from './data';

@Component({
    imports: [
         GanttModule
    ],
standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" #gantt height="430px"  [dataSource]="data"
        [taskFields]="taskSettings" [treeColumnIndex]='1'  [splitterSettings] = "splitterSettings">  
        <e-columns>
            <e-column field='TaskID' headerText='Task ID'  width=100></e-column>
            <e-column field='TaskName' headerText='Task Name' width=290 [valueAccessor]='concatenateFields'></e-column>
            <e-column field='Duration' headerText='Duration' width=90></e-column>
            <e-column field='Progress' headerText='Progress' width=120 [valueAccessor]='percentageFormatter'></e-column>
        </e-columns>   
       </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    // Data for Gantt
    public data?: object[];
    @ViewChild('gantt')
    public gantt?: GanttComponent;
    public taskSettings?: object;
    public splitterSettings?: object;
    public percentageFormatter = (field: string, valueAccessordata: object, column: object) => {
        return (valueAccessordata as any)["Progress"] + '%';
    }

    public concatenateFields = (field: string, valueAccessordata: object, column: object) => {
        return (valueAccessordata as any)[field] + ' - ' + (valueAccessordata as any)["TaskID"];
    }
    public ngOnInit(): void {
        this.data = GanttData;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
        this.splitterSettings = {
            position: '75%'
        };
    }
}
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 it is used to access a large number of data records or to perform complex data manipulations. To avoid performance issues, you can 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 Gantt chart component allows you to easily bind 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 will display the concatenated value of FirstName and LastName in the Name column of the gantt chart. Here’s an example of how this can be achieved:

import { BrowserModule } from '@angular/platform-browser';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';

import { Component, ViewEncapsulation, ViewChild, OnInit, NgModule } from '@angular/core';
import { GanttComponent } from '@syncfusion/ej2-angular-gantt';
import { GanttData } from './data';

@Component({
    imports: [
         GanttModule
    ],
standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" #gantt height="430px"  [dataSource]="data"
        [taskFields]="taskSettings" [treeColumnIndex]='1'  [splitterSettings] = "splitterSettings">   
        <e-columns>
            <e-column field='TaskID' headerText='Task ID'  width=100></e-column>
            <e-column field='TaskName' headerText='Task Name' width=290 ></e-column>
            <e-column field='Name' headerText='Full Name' textAlign='Right' [valueAccessor]='getConcatenatedNames' width=250></e-column>
            <e-column field='Duration' headerText='Duration' width=90></e-column>
            <e-column field='Progress' headerText='Progress' width=120 ></e-column>
        </e-columns>    
       </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    // Data for Gantt
    public data?: object[];
    @ViewChild('gantt')
    public gantt?: GanttComponent;
    public taskSettings?: object;
    public splitterSettings?: object;
    public getConcatenatedNames = (field: string, data: object) => {
        return (data as any)[field as string].map((s: { lastName: string, firstName: string }) => {
            return s.lastName || s.firstName;
        }).join(' ',);
    }
    public ngOnInit(): void {
        this.data = GanttData;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks',
        };
        this.splitterSettings = {
            position: '75%'
        };
    }
}
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

You can achieve an expression column in the Gantt chart by using the valueAccessor property. The valueAccessor property allows you to define a function that calculates the value for the expression column based on the values of other columns.

In this example, gantt chart has columns TaskID, TaskName, Duration, Progress, units, and unit price. An expression column called Total Price is added that calculates the total prices for value for each row based on the values of units and Total Price columns.

import { BrowserModule } from '@angular/platform-browser';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';

import { Component, ViewEncapsulation, ViewChild, OnInit, NgModule } from '@angular/core';
import { GanttComponent } from '@syncfusion/ej2-angular-gantt';
import { GanttData } from './data';

@Component({
    imports: [
         GanttModule
    ],
standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" #gantt height="430px"  [dataSource]="data"
        [taskFields]="taskSettings" [treeColumnIndex]='1' [splitterSettings] = "splitterSettings">    
        <e-columns>
            <e-column field='TaskID' headerText='Task ID'  width=100></e-column>
            <e-column field='TaskName' headerText='Task Name' width=290 ></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 field='TotalPrice' headerText='Total Price' [valueAccessor]='totalPrice' width=120 format='c2' type='number' textAlign='Right'></e-column>
            <e-column field='Duration' headerText='Duration' width=90></e-column>
            <e-column field='Progress' headerText='Progress' width=120 ></e-column>
        </e-columns>
       </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    // Data for Gantt
    public data?: object[];
    @ViewChild('gantt')
    public gantt?: GanttComponent;
    public taskSettings?: object;
    public splitterSettings?: object;
    totalPrice(field: string, data: { units: number, unitprice: number } | any, column: Object): number {
        return data.units * data.unitPrice;
    };
    public ngOnInit(): void {
        this.data = GanttData;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            totalPrice: 'TotalPrice',
            child: 'subtasks'
        };
        this.splitterSettings = {
            position: '75%'
        };

    }
}
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 number in the gantt chart for every rows, you can use the rowDataBound event. The rowDataBound event is triggered for each row in the gantt when the data is bound to the gantt chart.

Here is an example code snippet that demonstrates how to display serial numbers in a gantt chart using rowDataBound event:

import { BrowserModule } from '@angular/platform-browser';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';

import { Component, ViewEncapsulation, ViewChild, OnInit, NgModule } from '@angular/core';
import { GanttComponent, EditSettingsModel } from '@syncfusion/ej2-angular-gantt';
import { RowDataBoundEventArgs } from '@syncfusion/ej2-gantt';
import { GanttData } from './data';

@Component({
    imports: [
         GanttModule
    ],
standalone: true,
    selector: 'app-root',
    template:
        `<ejs-gantt id="ganttDefault" #gantt height="430px"  [dataSource]="data" (rowDataBound)='rowDataBound($event)'
         [editSettings]='editSettings' [taskFields]="taskSettings" [treeColumnIndex]='1' [splitterSettings] = "splitterSettings">             
            <e-columns>
                <e-column field='S.No' headerText='S.No' textAlign='Right' width=90 ></e-column>
                <e-column field='TaskID' headerText='Task ID' textAlign='Right' width=90 ></e-column>
                <e-column field='TaskName' headerText='Task Name' textAlign='Left' width=290></e-column>
                <e-column field='StartDate' headerText='Start Date' textAlign='Right' width=120 ></e-column>
                <e-column field='Duration' headerText='Duration' textAlign='Right' width=90 ></e-column>
                <e-column field='Progress' headerText='Progress' textAlign='Right' width=120></e-column>
            </e-columns>
       </ejs-gantt>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    // Data for Gantt
    public data?: object[];
    public editSettings?: EditSettingsModel;
    @ViewChild('gantt')
    public gantt?: GanttComponent;
    public taskSettings?: object;
    public splitterSettings?: object;
    public ngOnInit(): void {
        this.data = GanttData;
        this.taskSettings = {
            id: 'TaskID',
            name: 'TaskName',
            startDate: 'StartDate',
            duration: 'Duration',
            progress: 'Progress',
            child: 'subtasks'
        };
        this.editSettings = {
            allowEditing: true,
            allowAdding: true,
            allowDeleting: true,
        };
        this.splitterSettings = {
            position: '75%'
        };
    }
    rowDataBound({ row }: RowDataBoundEventArgs) {
        if (row) {
            var rowIndex = parseInt(row.getAttribute('aria-rowIndex') as string);
            var startIndex = 0;
            (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.