Syncfusion AI Assistant

How can I help you?

Sorting in React Gantt Chart Component

26 Mar 202624 minutes to read

The Syncfusion® React Gantt Chart component provides sorting functionality to arrange task data in ascending or descending order based on column values.

To enable sorting, set the allowSorting property to true. You can configure sorting behavior using the sortSettings property.

Sorting is applied by clicking a column header. For multi-column sorting, hold the CTRL key while selecting additional headers. To remove sorting from a specific column in a multi-sorted view, hold the SHIFT key and click the column header. For details on keyboard interactions, refer to the selection keyboard interaction documentation.

To enable sorting functionality, add the Sort service in the providers of the component.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort } 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'
  };
  return <GanttComponent dataSource={data} taskFields={taskFields} allowSorting={true} height='450px'>
    <Inject services={[Sort]} />
  </GanttComponent>
};
ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort, TaskFieldsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
  const taskFields: TaskFieldsModel = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    parentID: 'ParentID'
  };
  return <GanttComponent dataSource={data} taskFields={taskFields} allowSorting={true} height='450px'>
    <Inject services={[Sort]} />
  </GanttComponent>
};
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/33.1.44/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>

  • Gantt columns are sorted in the ascending order. If you click the already sorted column, the sort direction toggles.
  • To disable sorting for a particular column, set the columns.allowSorting property to false.
  • The Gantt columns are sorted in the ascending order. If you click the already sorted column, the sort direction toggles.
  • To disable sorting for a particular column, set the columns.allowSorting property to false.

Initial sorting

You can apply sorting during the initial render of the Syncfusion React Gantt Chart component by configuring the sortSettings.columns property. Each column should be defined with a specific field and direction, ensuring that the Gantt loads with the desired sort order applied to the specified columns.

The following code example shows how to add sorted columns during Gantt initialization, with field set to TaskID and direction to Descending, and another with field as TaskName and direction as Ascending.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort } 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 sortingOptions = { columns: [{ field: 'TaskID', direction: 'Descending' }, { field: 'TaskName', direction: 'Ascending' }] };
  return <GanttComponent dataSource={data} taskFields={taskFields} sortSettings={sortingOptions} allowSorting={true} height='450px'>
    <Inject services={[Sort]} />
  </GanttComponent>
};
ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort, SortSettingsModel, TaskFieldsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
  const taskFields: TaskFieldsModel = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    parentID: 'ParentID'
  };
  const sortingOptions: SortSettingsModel = { columns: [{ field: 'TaskID', direction: 'Descending' }, { field: 'TaskName', direction: 'Ascending' }] };
  return <GanttComponent dataSource={data} taskFields={taskFields} sortSettings={sortingOptions} allowSorting={true} height='450px'>
    <Inject services={[Sort]} />
  </GanttComponent>
};
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/33.1.44/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>

Sort columns externally

You can externally sort columns, remove a specific sort, or clear all sorting in the Syncfusion® React Gantt Chart component using button clicks.

Add sort columns

You can externally sort a column in the Syncfusion® React Gantt Chart component using the sortColumn method with parameters for column name, sort direction, and multi-sort configuration.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { GanttComponent, Inject, Sort } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
    let gantt;
    const taskFields = {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    };
    const splitterSettings = {
        columnIndex: 3
    }
    function clickHandler() {
        gantt.sortModule.sortColumn('TaskID', "Descending", false);
    }
    return (<div>
        <ButtonComponent onClick={clickHandler}>Sort Column</ButtonComponent>
        <GanttComponent dataSource={data} ref={g => gantt = g} taskFields={taskFields} allowSorting={true} splitterSettings={splitterSettings} height='450px'>
            <Inject services={[Sort]} />
        </GanttComponent></div>)
};
ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { GanttComponent, Inject, Sort, SplitterSettingsModel, TaskFieldsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
    let gantt: GanttComponent;
    const taskFields: TaskFieldsModel = {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    };
    const splitterSettings: SplitterSettingsModel = {
        columnIndex: 3
    }
    function clickHandler() {
        gantt.sortModule.sortColumn('TaskID', "Descending", false);
    }
    return (<div>
        <ButtonComponent onClick={clickHandler}>Sort Column</ButtonComponent>
        <GanttComponent dataSource={data} ref={g => gantt = g} taskFields={taskFields} allowSorting={true} splitterSettings={splitterSettings} height='450px'>
            <Inject services={[Sort]} />
        </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/33.1.44/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>

Remove sort columns

You can externally remove sorting from a specific column in the Syncfusion® React Gantt Chart component using the removeSortColumn method by passing the column name.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort, TaskFieldsModel, SplitterSettingsModel, ColumnModel, SortSettingsModel } from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { data } from './datasource';

function App() {
    const taskSettings = {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    };
    const columns = [
        { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '120' },
        { field: 'TaskName', headerText: 'Task Name', width: '250' },
        { field: 'StartDate', headerText: 'Start Date', width: '150' },
        { field: 'Duration', headerText: 'Duration', width: '150' },
        { field: 'Progress', headerText: 'Progress', width: '150' }
    ];
    const splitterSettings = { columnIndex: 3 };
    const sortSettings = {
        columns: [
            { field: 'TaskID', direction: 'Descending' },
            { field: 'TaskName', direction: 'Ascending' }
        ]
    };
    const columnOptions = [
        { text: 'Task ID', value: 'TaskID' },
        { text: 'Task Name', value: 'TaskName' },
        { text: 'Start Date', value: 'StartDate' },
        { text: 'Duration', value: 'Duration' },
        { text: 'Progress', value: 'Progress' }
    ];
    const field = { text: 'text', value: 'value' };
    let ganttInstance = null;
    let dropDownInstance = null;

    function removeSortColumn() {
        const selectedField = dropDownInstance.value;
        ganttInstance.removeSortColumn(selectedField);
    }

    return (
        <div>
            <div style=>
                <label style=>
                    Column name:
                </label>
                <DropDownListComponent width="120" dataSource={columnOptions} fields={field} index={0}
                    ref={(d) => (dropDownInstance = d)} />
                <ButtonComponent id="button" cssClass="e-outline" onClick={removeSortColumn}>
                    Remove sort column
                </ButtonComponent>
            </div>
            <GanttComponent id="ganttDefault" height="430px" dataSource={data} taskFields={taskSettings} columns={columns} splitterSettings={splitterSettings} sortSettings={sortSettings} allowSorting={true} ref={(g) => (ganttInstance = g)} >
                <Inject services={[Sort]} />
            </GanttComponent>
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort, TaskFieldsModel, SplitterSettingsModel, ColumnModel, SortSettingsModel } from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
import { data } from './datasource';

function App() {
    const taskSettings: TaskFieldsModel = {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    };
    const columns: ColumnModel[] = [
        { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '120' },
        { field: 'TaskName', headerText: 'Task Name', width: '250' },
        { field: 'StartDate', headerText: 'Start Date', width: '150' },
        { field: 'Duration', headerText: 'Duration', width: '150' },
        { field: 'Progress', headerText: 'Progress', width: '150' }
    ];
    const splitterSettings: SplitterSettingsModel = { columnIndex: 3 };
    const sortSettings: SortSettingsModel = {
        columns: [
            { field: 'TaskID', direction: 'Descending' },
            { field: 'TaskName', direction: 'Ascending' }
        ]
    };
    const columnOptions: object[] = [
        { text: 'Task ID', value: 'TaskID' },
        { text: 'Task Name', value: 'TaskName' },
        { text: 'Start Date', value: 'StartDate' },
        { text: 'Duration', value: 'Duration' },
        { text: 'Progress', value: 'Progress' }
    ];
    const field: object = { text: 'text', value: 'value' };
    let ganttInstance: GanttComponent | null = null;
    let dropDownInstance: DropDownListComponent | null = null;

    function removeSortColumn(): void {
        const selectedField = dropDownInstance.value as string;
        ganttInstance.removeSortColumn(selectedField);
    }

    return (
        <div>
            <div style=>
                <label style=>
                    Column name:
                </label>
                <DropDownListComponent width="120" dataSource={columnOptions} fields={field} index={0}
                    ref={(d) => (dropDownInstance = d)} />
                <ButtonComponent id="button" cssClass="e-outline" onClick={removeSortColumn}>
                    Remove sort column
                </ButtonComponent>
            </div>
            <GanttComponent id="ganttDefault" height="430px" dataSource={data} taskFields={taskSettings} columns={columns} splitterSettings={splitterSettings} sortSettings={sortSettings} allowSorting={true} ref={(g) => (ganttInstance = g)} >
                <Inject services={[Sort]} />
            </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/33.1.44/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>

Clear sorting

You can clear all sorted columns in the Syncfusion® React Gantt Chart component using the clearSorting method to reset the Gantt Chart to its unsorted state.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { GanttComponent, Inject, Sort } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
  let ganttInstance;
  const taskFields = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    dependency: 'Predecessor',
    parentID: 'ParentID'
  };
  const sortingOptions = {
    columns: [{ field: 'TaskID', direction: 'Descending' }, { field: 'TaskName', direction: 'Ascending' }]
  };
  function clickHandler() {
    ganttInstance.clearSorting();
  }
  return (<div>
    <ButtonComponent onClick={clickHandler}>Clear Sorting</ButtonComponent>
    <GanttComponent dataSource={data} taskFields={taskFields} ref={gantt => ganttInstance = gantt} allowSorting={true} sortSettings={sortingOptions} height='450px'>
      <Inject services={[Sort]} />
    </GanttComponent></div>)
};
ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { GanttComponent, Inject, Sort, SortSettingsModel, TaskFieldsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
  let ganttInstance: GanttComponent;
  const taskFields: TaskFieldsModel = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    dependency: 'Predecessor',
    parentID: 'ParentID'
  };
  const sortingOptions: SortSettingsModel = {
    columns: [{ field: 'TaskID', direction: 'Descending' }, { field: 'TaskName', direction: 'Ascending' }]
  };
  function clickHandler() {
    ganttInstance.clearSorting();
  }
  return (<div>
    <ButtonComponent onClick={clickHandler}>Clear Sorting</ButtonComponent>
    <GanttComponent dataSource={data} taskFields={taskFields} ref={gantt => ganttInstance = gantt} allowSorting={true} sortSettings={sortingOptions} height='450px'>
      <Inject services={[Sort]} />
    </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/33.1.44/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>

Customize sort icon

You can customize the sort icons in the Syncfusion® React Gantt Chart component by overriding the .e-icon-ascending and .e-icon-descending CSS classes using the content property, as shown below:

.e-gantt .e-icon-ascending::before {
    content: '\e7aa';
}

.e-gantt .e-icon-descending::before {
    content: '\e71f';
}
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort } 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'
  };
  return <GanttComponent dataSource={data} taskFields={taskFields} allowSorting={true} height='450px'>
    <Inject services={[Sort]} />
  </GanttComponent>
};
ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Sort, TaskFieldsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
  const taskFields: TaskFieldsModel = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    parentID: 'ParentID'
  };
  return <GanttComponent dataSource={data} taskFields={taskFields} allowSorting={true} height='450px'>
    <Inject services={[Sort]} />
  </GanttComponent>
};
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/33.1.44/tailwind3.css" rel="stylesheet" type="text/css" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/ej2-icons/styles/tailwind3.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%;
        }

        .e-gantt .e-icon-ascending::before {
            content: '\e7aa';
        }

        .e-gantt .e-icon-descending::before {
            content: '\e71f';
        }
    </style>
</head>

<body>
    <div id='root'>
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>

Custom sorting

You can customize the default sort behavior for a column in the Syncfusion® React Gantt Chart component by assigning a column.sortComparer function to define custom sorting logic.

The sorting process includes the following steps:

  1. Ascending → Descending → Clear Sorting (resets to original data source order).
  2. Child records are sorted within their respective parent groups.
  3. Null values in child records appear at the bottom of each parent group, not across the entire Gantt Chart dataset.
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, Inject, Sort } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";

function App() {

  const taskSettings = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const columns = [
    { field: "TaskID", headerText: "Task ID", textAlign: "Left", width: "120" },
    {
      field: "TaskName",
      headerText: "Task Name",
      width: "250",
      sortComparer: customSortComparer
    },
    { field: "StartDate", headerText: "Start Date", width: "150" },
    { field: "Duration", headerText: "Duration", width: "150" },
    { field: "Progress", headerText: "Progress", width: "150" }
  ];

  const splitterSettings = { columnIndex: 3 };

  const sortSettings = {
    columns: [
      { field: "TaskID", direction: "Descending" },
      { field: "StartDate", direction: "Ascending" }
    ]
  };

  function customSortComparer(reference, comparer) {
    if (reference < comparer) return -1;
    if (reference > comparer) return 1;
    return 0;
  }

  return (
    <GanttComponent
      height="430px"
      dataSource={data}
      taskFields={taskSettings}
      columns={columns}
      splitterSettings={splitterSettings}
      sortSettings={sortSettings}
      allowSorting={true}
    >
      <Inject services={[Sort]} />
    </GanttComponent>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, Inject, Sort, Columns, TaskFieldsModel, SplitterSettingsModel, SortSettingsModel } from "@syncfusion/ej2-react-gantt";

import { data } from "./datasource";

function App() {

  const taskSettings: TaskFieldsModel = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const columns: Columns[] = [
    { field: "TaskID", headerText: "Task ID", textAlign: "Left", width: "120" },
    {
      field: "TaskName",
      headerText: "Task Name",
      width: "250",
      sortComparer: customSortComparer
    },
    { field: "StartDate", headerText: "Start Date", width: "150" },
    { field: "Duration", headerText: "Duration", width: "150" },
    { field: "Progress", headerText: "Progress", width: "150" }
  ];

  const splitterSettings: SplitterSettingsModel = { columnIndex: 3 };

  const sortSettings: SortSettingsModel = {
    columns: [
      { field: "TaskID", direction: "Descending" },
      { field: "StartDate", direction: "Ascending" }
    ]
  };

  function customSortComparer(reference: any, comparer: any) {
    if (reference < comparer) return -1;
    if (reference > comparer) return 1;
    return 0;
  }

  return (
    <GanttComponent
      height="430px"
      dataSource={data}
      taskFields={taskSettings}
      columns={columns}
      splitterSettings={splitterSettings}
      sortSettings={sortSettings}
      allowSorting={true}
    >
      <Inject services={[Sort]} />
    </GanttComponent>
  );
}

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/33.1.44/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>

Display null values always at bottom

You can customize the sorting behavior in the Syncfusion® React Gantt Chart component to make null values consistently appear at the bottom, regardless of sort direction, by defining a column-level column.sortComparer function. By default, null values are placed at the bottom when sorting in ascending order and at the top when sorting in descending order. Applying a custom sortComparer helps override this default logic and is particularly useful when working with datasets where null entries should be visually separated from valid data.

The example below demonstrates how to display null values at the bottom of the Gantt Chart while sorting the TaskName column in both ascending and descending order.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, Inject, Sort } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";

function App() {

  let currentSortOrder = "Ascending";

  const taskSettings = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const columns = [
    { field: "TaskID", headerText: "Task ID", textAlign: "Left", width: "120" },
    {
      field: "TaskName",
      headerText: "Task Name",
      width: "250",
      sortComparer: customSortComparer
    },
    { field: "StartDate", headerText: "Start Date", width: "150" },
    { field: "Duration", headerText: "Duration", width: "150" },
    { field: "Progress", headerText: "Progress", width: "150" }
  ];

  const splitterSettings = { columnIndex: 3 };

  function actionBegin(args) {
    if (args.requestType === "sorting") {
      currentSortOrder = args.direction;
    }
  }

  // Custom comparer with null handling and dynamic sort order.
  function customSortComparer(reference, comparer) {
    const sortAsc = currentSortOrder === "Ascending";

    if (reference === null && comparer === null) return 0;
    if (reference === null) return 1;
    if (comparer === null) return -1;

    if (reference < comparer) return sortAsc ? -1 : 1;
    if (reference > comparer) return sortAsc ? 1 : -1;

    return 0;
  }

  return (
    <GanttComponent
      height="430px"
      dataSource={data}
      taskFields={taskSettings}
      columns={columns}
      splitterSettings={splitterSettings}
      allowSorting={true}
      actionBegin={actionBegin}
    >
      <Inject services={[Sort]} />
    </GanttComponent>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, Inject, Sort, SortEventArgs, Columns, TaskFieldsModel, SplitterSettings } from "@syncfusion/ej2-react-gantt";
import { data } from "./datasource";

function App() {

  let currentSortOrder: "Ascending" | "Descending" = "Ascending";

  const taskSettings: TaskFieldsModel = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const columns: Columns[] = [
    { field: "TaskID", headerText: "Task ID", textAlign: "Left", width: "120" },
    {
      field: "TaskName",
      headerText: "Task Name",
      width: "250",
      sortComparer: customSortComparer
    },
    { field: "StartDate", headerText: "Start Date", width: "150" },
    { field: "Duration", headerText: "Duration", width: "150" },
    { field: "Progress", headerText: "Progress", width: "150" }
  ];

  const splitterSettings: SplitterSettings = { columnIndex: 3 };

  function actionBegin(args: SortEventArgs): void {
    if (args.requestType === "sorting") {
      currentSortOrder = args.direction as "Ascending" | "Descending";
    }
  }

  // Custom comparer with null handling and dynamic sort order.
  function customSortComparer(reference: string | null, comparer: string | null): number {
    const sortAsc = currentSortOrder === "Ascending";

    if (reference === null && comparer === null) return 0;
    if (reference === null) return 1;
    if (comparer === null) return -1;

    if (reference < comparer) return sortAsc ? -1 : 1;
    if (reference > comparer) return sortAsc ? 1 : -1;

    return 0;
  }

  return (
    <GanttComponent
      height="430px"
      dataSource={data}
      taskFields={taskSettings}
      columns={columns}
      splitterSettings={splitterSettings}
      allowSorting={true}
      actionBegin={actionBegin}
    >
      <Inject services={[Sort]} />
    </GanttComponent>
  );
}

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/33.1.44/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>

Sorting custom columns

You can sort custom columns of various types such as string or numeric in the Syncfusion® React Gantt Chart component by adding them to the column collection. Initial sorting can be configured using the sortSettings property, or sorting can be triggered dynamically through external actions such as a button click.

The following code snippet demonstrates how to sort the CustomColumn using an external button.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, Inject, Sort, ColumnsDirective, ColumnDirective } from "@syncfusion/ej2-react-gantt";
import { ButtonComponent } from "@syncfusion/ej2-react-buttons";
import { data } from "./datasource";

function App() {
    let ganttInstance = null;
    const taskSettings = {
        id: "TaskID",
        name: "TaskName",
        startDate: "StartDate",
        duration: "Duration",
        progress: "Progress",
        parentID: "ParentID"
    };
    const splitterSettings = { columnIndex: 3 };
    function sort() {
        if (ganttInstance) {
            ganttInstance.sortModule.sortColumn(
                "CustomColumn",
                "Ascending",
                false
            );
        }
    }
    return (
        <div>
            <ButtonComponent cssClass='e-outline' onClick={sort}>Sort Custom Column</ButtonComponent>
            <br />
            <br />

            <GanttComponent
                id="ganttDefault"
                height="430px"
                dataSource={data}
                taskFields={taskSettings}
                splitterSettings={splitterSettings}
                allowSorting={true}
                ref={g => ganttInstance = g}
            >
                <ColumnsDirective>
                    <ColumnDirective field="TaskID" headerText="Task ID" width="100" />
                    <ColumnDirective field="TaskName" headerText="Task Name" width="200" />
                    <ColumnDirective field="StartDate" headerText="Start Date" width="150" />
                    <ColumnDirective field="Duration" headerText="Duration" width="100" />
                    <ColumnDirective field="Progress" headerText="Progress" width="100" />
                    <ColumnDirective field="CustomColumn" headerText="Custom Column" width="150" />
                </ColumnsDirective>

                <Inject services={[Sort]} />
            </GanttComponent>
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById("root"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    GanttComponent,
    Inject,
    Sort,
    ColumnsDirective,
    ColumnDirective,
    SortDirection,
    SplitterSettingsModel
} from "@syncfusion/ej2-react-gantt";
import { ButtonComponent } from "@syncfusion/ej2-react-buttons";
import { data } from "./datasource";

function App() {
    let ganttInstance: GanttComponent | null = null;
    const taskSettings = {
        id: "TaskID",
        name: "TaskName",
        startDate: "StartDate",
        duration: "Duration",
        progress: "Progress",
        parentID: "ParentID"
    };
    const splitterSettings: SplitterSettingsModel = { columnIndex: 3 };
    function sort(): void {
        if (ganttInstance) {
            ganttInstance.sortModule.sortColumn(
                "CustomColumn",
                "Ascending" as SortDirection,
                false
            );
        }
    }

    return (
        <div>
            <ButtonComponent cssClass='e-outline' onClick={sort}>Sort Custom Column</ButtonComponent>
            <br />
            <br />

            <GanttComponent
                id="ganttDefault"
                height="430px"
                dataSource={data}
                taskFields={taskSettings}
                splitterSettings={splitterSettings}
                allowSorting={true}
                ref={g => ganttInstance = g}
            >
                <ColumnsDirective>
                    <ColumnDirective field="TaskID" headerText="Task ID" width="100" />
                    <ColumnDirective field="TaskName" headerText="Task Name" width="200" />
                    <ColumnDirective field="StartDate" headerText="Start Date" width="150" />
                    <ColumnDirective field="Duration" headerText="Duration" width="100" />
                    <ColumnDirective field="Progress" headerText="Progress" width="100" />
                    <ColumnDirective field="CustomColumn" headerText="Custom Column" width="150" />
                </ColumnsDirective>

                <Inject services={[Sort]} />
            </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/33.1.44/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>

Prevent sorting on specific columns

You can prevent sorting on specific columns in the Syncfusion® React Gantt Chart component by handling the actionBegin or actionComplete events. Alternatively, you can disable sorting for a column by setting its allowSorting property to false in the column configuration.

The following sample demonstrates how to prevent sorting for the TaskID and StartDate columns.

import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  GanttComponent,
  Inject,
  Sort,
  ColumnsDirective,
  ColumnDirective
} from "@syncfusion/ej2-react-gantt";

import { data } from "./datasource";

function App() {

  let ganttInstance = null;
  let message = "";

  const taskSettings = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const splitterSettings = { columnIndex: 3 };

  function actionBegin(args) {
    if (args.requestType === "sorting" && args.columnName === "TaskID") {
      message = `${args.requestType} action cancelled for ${args.columnName} column`;
      args.cancel = true;
      updateMessage();
    }
  }

  function actionComplete(args) {
    if (args.requestType === "sorting" && args.columnName === "StartDate") {
      message = `${args.requestType} action cancelled for ${args.columnName} column`;
      updateMessage();
    }
  }

  function updateMessage() {
    const msgElement = document.getElementById("message");
    if (msgElement) msgElement.innerText = message;
  }

  return (
    <div>
      <div style=>
        <p id="message" style=></p>
      </div>

      <GanttComponent
        id="ganttDefault"
        height="430px"
        dataSource={data}
        taskFields={taskSettings}
        splitterSettings={splitterSettings}
        allowSorting={true}
        actionBegin={actionBegin}
        actionComplete={actionComplete}
        ref={g => ganttInstance = g}
      >
        <ColumnsDirective>
          <ColumnDirective field="TaskID" headerText="Task ID" textAlign="Left" width="100" />
          <ColumnDirective field="TaskName" headerText="Task Name" width="250" />
          <ColumnDirective field="StartDate" headerText="Start Date" width="150" />
          <ColumnDirective field="Duration" headerText="Duration" width="150" />
          <ColumnDirective field="Progress" headerText="Progress" width="150" />
        </ColumnsDirective>

        <Inject services={[Sort]} />
      </GanttComponent>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  GanttComponent,
  Inject,
  Sort,
  ColumnsDirective,
  ColumnDirective
} from "@syncfusion/ej2-react-gantt";

import { data } from "./datasource";

function App() {

  let ganttInstance: GanttComponent | null = null;
  let message: string = "";

  const taskSettings = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const splitterSettings = { columnIndex: 3 };

  function actionBegin(args: any): void {
    if (args.requestType === "sorting" && args.columnName === "TaskID") {
      message = `${args.requestType} action cancelled for ${args.columnName} column`;
      args.cancel = true;
      updateMessage();
    }
  }

  function actionComplete(args: any): void {
    if (args.requestType === "sorting" && args.columnName === "StartDate") {
      message = `${args.requestType} action cancelled for ${args.columnName} column`;
      updateMessage();
    }
  }

  function updateMessage() {
    const msgElement = document.getElementById("message");
    if (msgElement) msgElement.innerText = message;
  }

  return (
    <div>
      <div style=>
        <p id="message" style=></p>
      </div>

      <GanttComponent
        id="ganttDefault"
        height="430px"
        dataSource={data}
        taskFields={taskSettings}
        splitterSettings={splitterSettings}
        allowSorting={true}
        actionBegin={actionBegin}
        actionComplete={actionComplete}
        ref={g => ganttInstance = g}
      >
        <ColumnsDirective>
          <ColumnDirective field="TaskID" headerText="Task ID" textAlign="Left" width="100" />
          <ColumnDirective field="TaskName" headerText="Task Name" width="250" />
          <ColumnDirective field="StartDate" headerText="Start Date" width="150" />
          <ColumnDirective field="Duration" headerText="Duration" width="150" />
          <ColumnDirective field="Progress" headerText="Progress" width="150" />
        </ColumnsDirective>

        <Inject services={[Sort]} />
      </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/33.1.44/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>

Disable clear sort

By default, clicking a column header switches the sort order between ascending, descending, and unsorted. To restrict this to only ascending and descending, set sortSettings.allowUnsort to false. This ensures sorting remains active without reverting to an unsorted state.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Sort, Inject } 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 columns = [
    { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '100' },
    { field: 'TaskName', headerText: 'Task Name', width: '250' },
    { field: 'StartDate', headerText: 'Start Date', width: '150' },
    { field: 'Duration', headerText: 'Duration', width: '150' },
    { field: 'Progress', headerText: 'Progress', width: '150' }
  ];

  const splitterSettings = {
    columnIndex: 3
  };

  const sortSettings = {
    allowUnsort: false
  };
  return (
    <div>
      <GanttComponent
        height="430px"
        dataSource={data}
        taskFields={taskFields}
        columns={columns}
        splitterSettings={splitterSettings}
        sortSettings={sortSettings}
        allowSorting={true}
      >
        <Inject services={[Sort]} />
      </GanttComponent>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById('root'));
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Sort, Inject, TaskFieldsModel, Columns, SplitterSettings, SortSettings } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
  const taskFields: TaskFieldsModel = {
    id: 'TaskID',
    name: 'TaskName',
    startDate: 'StartDate',
    duration: 'Duration',
    progress: 'Progress',
    parentID: 'ParentID'
  };

  const columns: Columns[] = [
    { field: 'TaskID', headerText: 'Task ID', textAlign: 'Left', width: '100' },
    { field: 'TaskName', headerText: 'Task Name', width: '250' },
    { field: 'StartDate', headerText: 'Start Date', width: '150' },
    { field: 'Duration', headerText: 'Duration', width: '150' },
    { field: 'Progress', headerText: 'Progress', width: '150' }
  ];

  const splitterSettings: SplitterSettings = {
    columnIndex: 3
  };

  const sortSettings: SortSettings = {
    allowUnsort: false
  };
  return (
    <div>
      <GanttComponent
        height="430px"
        dataSource={data}
        taskFields={taskFields}
        columns={columns}
        splitterSettings={splitterSettings}
        sortSettings={sortSettings}
        allowSorting={true}
      >
        <Inject services={[Sort]} />
      </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/33.1.44/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>

Touch interaction

To perform a tap action on a column header in the Syncfusion® React Gantt Chart component, the sorting operation is triggered for the selected column. A popup appears when multi-column sorting is enabled. To sort multiple columns, tap the popup and then tap the desired column headers. The following screenshot shows Gantt touch sorting.

Multiple Sorting