Column Rendering in React Gantt Chart Component
18 Nov 201824 minutes to read
The React Gantt Chart component supports column rendering to control data presentation. Column definitions act as the data schema and support operations such as sorting and filtering. The field property is required to map data source values to columns and must be defined for features like complex binding and template-based actions.
- If the
fieldis not defined in the dataSource, the column will display empty values.- To enable CRUD, filtering, or searching, the
fieldmust be defined for template columns.
Define columns manually
To manually define columns in the Gantt Chart component, use e-columns and set properties like field, headerText and width. This enables customization of column behavior and appearance based on specific requirements.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = {
position: "75%"
};
return <div><GanttComponent dataSource={data} taskFields={taskFields} height="450px" splitterSettings={splitterSettings}>
<ColumnsDirective>
<ColumnDirective field="TaskID" > </ColumnDirective>
<ColumnDirective field="TaskName" headerText="Task Name" width="180" > </ColumnDirective>
<ColumnDirective field="StartDate" headerText="Start Date" width="180" > </ColumnDirective>
<ColumnDirective field="Duration" headerText="Duration" width="100" > </ColumnDirective>
<ColumnDirective field="Progress" headerText="Progress" width="120" > </ColumnDirective>
</ColumnsDirective>
</GanttComponent></div>
};
ReactDOM.render(<App />, document.getElementById("root"));import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = {
position: "75%"
};
return <div><GanttComponent dataSource={data} taskFields={taskFields} height="450px" splitterSettings={splitterSettings}>
<ColumnsDirective>
<ColumnDirective field="TaskID" > </ColumnDirective>
<ColumnDirective field="TaskName" headerText="Task Name" width="180" > </ColumnDirective>
<ColumnDirective field="StartDate" headerText="Start Date" width="180" > </ColumnDirective>
<ColumnDirective field="Duration" headerText="Duration" width="100" > </ColumnDirective>
<ColumnDirective field="Progress" headerText="Progress" width="120" > </ColumnDirective>
</ColumnsDirective>
</GanttComponent></div>
};
ReactDOM.render(<App />, document.getElementById("root"));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Auto generated columns
The Gantt Chart component automatically generates columns when the columns property is either empty or undefined during initialization, binding all fields from the dataSource as individual Gantt columns.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = {
position: "75%"
};
return <div><GanttComponent dataSource={data} taskFields={taskFields} height="450px" splitterSettings={splitterSettings} treeColumnIndex={1}>
</GanttComponent></div>
};
ReactDOM.render(<App />, document.getElementById("root"));import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = {
position: "75%"
};
return <div><GanttComponent dataSource={data} taskFields={taskFields} height="450px" splitterSettings={splitterSettings} treeColumnIndex={1}>
</GanttComponent></div>
};
ReactDOM.render(<App />, document.getElementById("root"));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Dynamic column generation
You can dynamically generate columns in the Gantt Chart component at runtime based on the provided data. This is useful when the column structure needs to adapt to user requirements or dynamic data sources.
Using valueAccessor property
The valueAccessor property is used to format column data in the Gantt Chart component. It accepts a function that returns a custom display value using the following two arguments:
-
field: The column’s data field. -
data: The data record for the row.
In the following example, percentageFormatter returns the progress value with a % sign, while concatenateFields returns a combined string of TaskName and TaskID.
import * as React from "react";
import { getValue } from '@syncfusion/ej2-base';
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = {
position: "75%"
};
const concatenateFields = (field, data) => {
return data[field] + '-' + getValue('TaskID', data);
};
const percentageFormatter = (field, data) => {
return data[field] + '%';
};
return <div><GanttComponent dataSource={data} taskFields={taskFields} height="450px" splitterSettings={splitterSettings}>
<ColumnsDirective>
<ColumnDirective field="TaskID" > </ColumnDirective>
<ColumnDirective field="TaskName" headerText="Task Name" width="180" valueAccessor={concatenateFields} > </ColumnDirective>
<ColumnDirective field="StartDate" headerText="Start Date" width="180" > </ColumnDirective>
<ColumnDirective field="Duration" headerText="Duration" width="100" > </ColumnDirective>
<ColumnDirective field="Progress" headerText="Progress" width="120" valueAccessor={percentageFormatter} > </ColumnDirective>
</ColumnsDirective>
</GanttComponent></div>
};
ReactDOM.render(<App />, document.getElementById("root"));import * as React from "react";
import { getValue } from '@syncfusion/ej2-base';
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = {
position: "75%"
};
const concatenateFields = (field: string, data: object, ) => {
return data[field] + '-' + getValue('TaskID', data);
};
const percentageFormatter = (field: string, data: object, ) => {
return data[field] + '%';
};
return <div><GanttComponent dataSource={data} taskFields={taskFields} height="450px" splitterSettings={splitterSettings}>
<ColumnsDirective>
<ColumnDirective field="TaskID" > </ColumnDirective>
<ColumnDirective field="TaskName" headerText="Task Name" width="180" valueAccessor={concatenateFields} > </ColumnDirective>
<ColumnDirective field="StartDate" headerText="Start Date" width="180" > </ColumnDirective>
<ColumnDirective field="Duration" headerText="Duration" width="100" > </ColumnDirective>
<ColumnDirective field="Progress" headerText="Progress" width="120" valueAccessor={percentageFormatter} > </ColumnDirective>
</ColumnsDirective>
</GanttComponent></div>
};
ReactDOM.render(<App />, document.getElementById("root"));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>The
valueAccessorfunction may impact performance when used with large datasets or complex logic. To improve rendering speed, enable the virtualization feature so that only visible rows are processed and displayed.
Display array type columns
The Gantt Chart component supports binding an array of objects to a column using the valueAccessor property. It accepts a function that returns a custom display value, which is then displayed in the column.
In the following example, the Name column shows the combined value of FirstName and LastName by using a custom function defined in valueAccessor.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
GanttComponent,
ColumnsDirective,
ColumnDirective,
} from '@syncfusion/ej2-react-gantt';
import { GanttData } from './datasource';
function App() {
let gantt;
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const splitterSettings = {
position: '75%'
};
const getConcatenatedNames = (field, rowData) => {
return rowData.Name.map(
(person) => person.lastName || person.firstName
).join(' ');
};
return (
<GanttComponent
ref={(g) => (gantt = g)}
height="430px"
dataSource={GanttData}
taskFields={taskFields}
treeColumnIndex={1}
splitterSettings={splitterSettings}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="290" />
<ColumnDirective
field="Name"
headerText="Full Name"
textAlign="Right"
valueAccessor={getConcatenatedNames}
width="250"
/>
<ColumnDirective field="Duration" headerText="Duration" width="90" />
<ColumnDirective field="Progress" headerText="Progress" width="120" />
</ColumnsDirective>
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
GanttComponent,
ColumnsDirective,
ColumnDirective,
TaskFieldsModel,
SplitterSettingsModel
} from '@syncfusion/ej2-react-gantt';
import { GanttData } from './datasource';
function App() {
let gantt: GanttComponent | null;
const taskFields: TaskFieldsModel = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID'
};
const splitterSettings: SplitterSettingsModel = {
position: '75%'
};
const getConcatenatedNames = (field: string, rowData: GanttTask): string => {
return rowData.Name.map(
(person: PersonName) => person.lastName || person.firstName
).join(' ');
};
return (
<GanttComponent
ref={(g: GanttComponent) => (gantt = g)}
height="430px"
dataSource={GanttData}
taskFields={taskFields}
treeColumnIndex={1}
splitterSettings={splitterSettings}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="290" />
<ColumnDirective
field="Name"
headerText="Full Name"
textAlign="Right"
valueAccessor={getConcatenatedNames}
width="250"
/>
<ColumnDirective field="Duration" headerText="Duration" width="90" />
<ColumnDirective field="Progress" headerText="Progress" width="120" />
</ColumnsDirective>
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
export interface PersonName {
firstName: string;
lastName: string;
}
export interface GanttTask {
TaskID: number;
ParentID?: number;
TaskName: string;
StartDate: Date;
Duration: number;
Progress: number;
Name: PersonName[];
}<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>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 component using the valueAccessor property. It accepts a function that returns a calculated value, which is displayed in the column based on other column values.
In the following example, the chart includes columns like TaskID, TaskName, Duration, Progress, units, and unit price. A Total Price column is added to display the result of multiplying units and unit price for each row.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { GanttData } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
duration: "Duration",
progress: "Progress",
parentID: "parentID",
units: "Units",
unitPrice: "UnitPrice"
};
const splitterSettings = { position: "75%" };
const totalPrice = (field, data, column) => {
return Number(data.units) * Number(data.unitPrice);
};
return (
<div>
<GanttComponent
dataSource={GanttData}
taskFields={taskFields}
height="450px"
splitterSettings={splitterSettings}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="290" />
<ColumnDirective field="Units" headerText="Units" width="120" textAlign="Right" />
<ColumnDirective field="UnitPrice" headerText="Unit Price" width="120" textAlign="Right" />
<ColumnDirective field="TotalPrice" headerText="Total Price" width="120" format="c2" type="number" textAlign="Right" valueAccessor={totalPrice} />
<ColumnDirective field="Duration" headerText="Duration" width="90" />
<ColumnDirective field="Progress" headerText="Progress" width="120" />
</ColumnsDirective>
</GanttComponent>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { GanttData } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
duration: "Duration",
progress: "Progress",
parentID: "parentID",
units: "Units",
unitPrice: "UnitPrice"
};
const splitterSettings = { position: "75%" };
const totalPrice = (field: string, data: any, column: object) => {
return Number(data.units) * Number(data.unitPrice);
};
return (
<div>
<GanttComponent
dataSource={GanttData}
taskFields={taskFields}
height="450px"
splitterSettings={splitterSettings}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="290" />
<ColumnDirective field="Units" headerText="Units" width="120" textAlign="Right" />
<ColumnDirective field="UnitPrice" headerText="Unit Price" width="120" textAlign="Right" />
<ColumnDirective field="TotalPrice" headerText="Total Price" width="120" format="c2" type="number" textAlign="Right" valueAccessor={totalPrice} />
<ColumnDirective field="Duration" headerText="Duration" width="90" />
<ColumnDirective field="Progress" headerText="Progress" width="120" />
</ColumnsDirective>
</GanttComponent>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Since custom values are displayed in the Total Price column, operations like sorting and filtering are not supported for this column.
Display serial number
You can display serial numbers for each row in the Gantt Chart component using the rowDataBound event. This event triggers when data is bound to each row, allowing you to assign and display a serial number directly in the column.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = { position: "75%" };
const rowDataBound = (args) => {
const row = args.row;
if (row) {
const rowIndex = parseInt(row.getAttribute("aria-rowindex") || "0", 10);
const cells = row.querySelectorAll(".e-rowcell");
if (cells.length > 0) {
cells[0].textContent = rowIndex.toString();
}
}
};
return (
<div>
<GanttComponent
dataSource={data}
taskFields={taskFields}
height="450px"
splitterSettings={splitterSettings}
rowDataBound={rowDataBound}
treeColumnIndex={1}
>
<ColumnsDirective>
<ColumnDirective field="SNo" headerText="S.No" width="100" />
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="290" />
<ColumnDirective field="StartDate" headerText="StartDate" width="120" textAlign="Right" />
<ColumnDirective field="Duration" headerText="Duration" width="90" />
<ColumnDirective field="Progress" headerText="Progress" width="120" />
</ColumnsDirective>
</GanttComponent>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, ColumnsDirective, ColumnDirective, RowDataBoundEventArgs } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
duration: "Duration",
progress: "Progress",
parentID: "ParentID"
};
const splitterSettings = { position: "75%" };
const rowDataBound = (args: RowDataBoundEventArgs) => {
const row = args.row;
if (row) {
const rowIndex = parseInt(row.getAttribute("aria-rowindex") || "0", 10);
const cells = row.querySelectorAll(".e-rowcell");
if (cells.length > 0) {
cells[0].textContent = rowIndex.toString();
}
}
};
return (
<div>
<GanttComponent
dataSource={data}
taskFields={taskFields}
height="450px"
splitterSettings={splitterSettings}
rowDataBound={rowDataBound}
treeColumnIndex={1}
>
<ColumnsDirective>
<ColumnDirective field="SNo" headerText="S.No" width="100" />
<ColumnDirective field="TaskID" headerText="Task ID" width="100" />
<ColumnDirective field="TaskName" headerText="Task Name" width="290" />
<ColumnDirective field="StartDate" headerText="StartDate" width="120" textAlign="Right" />
<ColumnDirective field="Duration" headerText="Duration" width="90" />
<ColumnDirective field="Progress" headerText="Progress" width="120" />
</ColumnsDirective>
</GanttComponent>
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>Since custom values are displayed in the S.No column, data operations such as sorting and filtering are not supported for this column.