Cell Selection in EJ2 TypeScript Gantt Chart Control

27 May 202624 minutes to read

Cell selection in the Gantt Chart control enables interactive selection of specific cells or ranges of cells within the grid. You may select cells using mouse clicks or arrow keys (up, down, left, right). This is useful for highlighting, manipulating, or performing operations on particular Gantt cells.

Single cell selection

Single cell selection in the Gantt Chart is enabled by setting selectionSettings.mode to Cell and selectionSettings.type to Single. This allows selecting only one cell at a time.

import { Gantt, Selection } from '@syncfusion/ej2-gantt';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let gantt: Gantt = new Gantt({
    dataSource: GanttData,
    height: '370px',
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        endDate: 'EndDate',
        duration: 'Duration',
        progress: 'Progress',
        dependency: 'Predecessor',
        parentID: 'ParentID'
    },
    selectionSettings: {
        mode: 'Cell',
        type: 'Single'
    }
});

gantt.appendTo('#Gantt');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
	<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='Gantt'></div>        
    </div>
</body>

</html>

Multiple cell selection

Multiple cell selection in the Gantt Chart is enabled by setting selectionSettings.mode to Cell and selectionSettings.type to Multiple. This allows selecting multiple cells at a time by holding the Ctrl key while clicking on each desired cell.

import { Gantt, Selection } from '@syncfusion/ej2-gantt';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let gantt: Gantt = new Gantt({
    dataSource: GanttData,
    height: '370px',
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        endDate: 'EndDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    },
    selectionSettings: {
        mode: 'Cell',
        type: 'Multiple'
    }
});

gantt.appendTo('#Gantt');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='Gantt'></div>
    </div>
</body>

</html>

Cell selection mode

Cell selection mode controls how cells or ranges are selected. Set the desired mode using selectionSettings.cellSelectionMode:

  • Flow (default): Selects a continuous flow of cells between the start and end indices across rows.
  • Box: Selects a rectangular range covering specified rows and columns.
  • BoxWithBorder: Similar to Box mode, but applies a border for better visual distinction of the selected range.

For cell selection modes, selectionSettings.mode must be Cell or Both, and type must be Multiple.

The following example demonstrates how to change both the selection mode and the cell selection mode using a DropDownList control.

import { Gantt, Selection } from '@syncfusion/ej2-gantt';
import { DropDownList, ChangeEventArgs } from '@syncfusion/ej2-dropdowns';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let gantt: Gantt = new Gantt({
    dataSource: GanttData,
    height: '370px',
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        endDate: 'EndDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    },
    selectionSettings: {
        mode: 'Cell',
        type: 'Multiple',
        cellSelectionMode: 'Flow'
    }
});

gantt.appendTo('#Gantt');

let modeDropDown: DropDownList = new DropDownList({
    dataSource: [
        { text: 'Cell', value: 'Cell' },
        { text: 'Row', value: 'Row' },
        { text: 'Both', value: 'Both' }
    ],
    fields: { text: 'text', value: 'value' },
    index: 0,
    change: (args: ChangeEventArgs) => {
        gantt.treeGrid.grid.selectionSettings.mode = args.value as any;
        gantt.treeGrid.grid.refresh();
    }
});
modeDropDown.appendTo('#selectionMode');

let cellModeDropDown: DropDownList = new DropDownList({
    dataSource: [
        { text: 'Flow', value: 'Flow' },
        { text: 'Box', value: 'Box' },
        { text: 'BoxWithBorder', value: 'BoxWithBorder' }
    ],
    fields: { text: 'text', value: 'value' },
    index: 0,
    change: (args: ChangeEventArgs) => {
        gantt.treeGrid.grid.selectionSettings.cellSelectionMode = args.value as any;
    }
});
cellModeDropDown.appendTo('#cellSelectionMode');
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div style="display: flex; gap: 20px; padding-bottom: 20px;">
            <div>
                <label style="font-weight: bold;">Select Mode:</label>
                <input type="text" id="selectionMode" />
            </div>

            <div>
                <label style="font-weight: bold;">Cell Selection Style:</label>
                <input type="text" id="cellSelectionMode" />
            </div>
        </div>
        <div id='Gantt'></div>
    </div>
</body>

</html>

Select cells externally

You may programmatically select a single row, multiple cells, or a range of cells in the Gantt Chart using built-in methods.

Single cell selection

Select a specific cell in the Gantt Chart by calling the selectCell method and providing the desired row and column indexes as arguments.

import { Gantt, Selection } from '@syncfusion/ej2-gantt';
import { TextBox } from '@syncfusion/ej2-inputs';
import { Button } from '@syncfusion/ej2-buttons';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let gantt: Gantt = new Gantt({
    dataSource: GanttData,
    height: '370px',
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    },
    selectionSettings: {
        mode: 'Cell',
        type: 'Single'
    }
});
gantt.appendTo('#Gantt');

let rowTextBox: TextBox = new TextBox({
    width: '100'
});
rowTextBox.appendTo('#rowIndex');

let cellTextBox: TextBox = new TextBox({
    width: '100'
});
cellTextBox.appendTo('#cellIndex');

let selectBtn: Button = new Button();
selectBtn.appendTo('#selectCell');

document.getElementById('selectCell')!.addEventListener('click', () => {
    let rowIndex: number = parseInt(rowTextBox.value as string, 10);
    let cellIndex: number = parseInt(cellTextBox.value as string, 10);

    if (!isNaN(rowIndex) && !isNaN(cellIndex)) {
        gantt.selectCell({ rowIndex, cellIndex });
    }
});
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div style="display:flex; align-items:center; gap:10px; margin-bottom:10px;">
        <label style="font-weight:bold;">Enter the row index:</label>
        <input id="rowIndex" type="text" />

        <label style="font-weight:bold;">Enter the cell index:</label>
        <input id="cellIndex" type="text" />

        <button id="selectCell">Select Cell</button>
    </div>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='Gantt'></div>
    </div>
</body>

</html>

Multiple cell selection

Select multiple cells in the Gantt Chart by calling the selectCells method and providing an array of the row and column indexes for each target cell.

import { Gantt, Selection } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let gantt: Gantt = new Gantt({
    height: '370px',
    dataSource: GanttData,
    enableHover: true,
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    },
    selectionSettings: {
        mode: 'Cell',
        type: 'Multiple'
    },
    columns: [
        { field: 'TaskID', headerText: 'ID', width: 80 },
        { field: 'TaskName', headerText: 'Task Name', width: 250 },
        { field: 'StartDate', headerText: 'Start Date' },
        { field: 'Duration', headerText: 'Duration' },
        { field: 'Progress', headerText: 'Progress' }
    ]
});

gantt.appendTo('#Gantt');

function selectCells(rowIndex: number, cellIndex: number): void {
    gantt.clearSelection();
    gantt.selectCells([
        { rowIndex: rowIndex, cellIndexes: [cellIndex] }
    ]);
}

['btn0', 'btn1', 'btn2', 'btn3', 'btn4', 'btn5', 'btn6', 'btn7', 'btn8'].forEach((id, i) => {
    new Button().appendTo('#' + id);
});

(document.getElementById('btn0') as HTMLElement).onclick = () => selectCells(0, 0);
(document.getElementById('btn1') as HTMLElement).onclick = () => selectCells(1, 1);
(document.getElementById('btn2') as HTMLElement).onclick = () => selectCells(2, 2);
(document.getElementById('btn3') as HTMLElement).onclick = () => selectCells(3, 3);
(document.getElementById('btn4') as HTMLElement).onclick = () => selectCells(4, 4);
(document.getElementById('btn5') as HTMLElement).onclick = () => selectCells(5, 0);
(document.getElementById('btn6') as HTMLElement).onclick = () => selectCells(6, 1);
(document.getElementById('btn7') as HTMLElement).onclick = () => selectCells(7, 2);
(document.getElementById('btn8') as HTMLElement).onclick = () => selectCells(3, 4);
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div style="display:flex;flex-wrap:wrap;gap:10px;padding:10px 0 20px 0">
        <button id="btn0">Select [0,0]</button>
        <button id="btn1">Select [1,1]</button>
        <button id="btn2">Select [2,2]</button>
        <button id="btn3">Select [3,3]</button>
        <button id="btn4">Select [4,4]</button>
        <button id="btn5">Select [5,0]</button>
        <button id="btn6">Select [6,1]</button>
        <button id="btn7">Select [7,2]</button>
        <button id="btn8">Select [3,4]</button>
    </div>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div id='Gantt'></div>
    </div>
</body>

</html>

Get selected cell information

To retrieve information about selected cells in the Gantt Chart, use methods like getSelectedRowCellIndexes method to get the list of row and column indexes for selected cells, and the getCellSelectedRecords method to retrieve the related data objects for each selected cell.

import { Gantt, Selection } from '@syncfusion/ej2-gantt';
import { Button } from '@syncfusion/ej2-buttons';
import { Dialog } from '@syncfusion/ej2-popups';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let ganttObj: Gantt = new Gantt({
    height: '370px',
    dataSource: GanttData,
    selectionSettings: {
        mode: 'Cell',
        type: 'Multiple'
    },
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        endDate: 'EndDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    }
});

ganttObj.appendTo('#Gantt');

let dialogObj: Dialog = new Dialog({
    header: 'Selected Cell Details',
    visible: false,
    width: '600px',
    height: '300px',
    showCloseIcon: true,
    position: { X: 300, Y: 100 }
});

dialogObj.appendTo('#Dialog');

let showBtn: Button = new Button();
showBtn.appendTo('#showDetails');

document.getElementById('showDetails')!.addEventListener('click', () => {

    let selectedRecords: any[] = ganttObj.selectionModule.getCellSelectedRecords();
    let selectedIndexes: any[] = ganttObj.selectionModule.getSelectedRowCellIndexes();
    let container = document.getElementById('details-container') as HTMLElement;

    let html = `
    <table border="1" cellpadding="6" cellspacing="0" style="width:100%;border-collapse:collapse">
        <thead>
            <tr>
                <th>Row Index</th>
                <th>Cell Index</th>
                <th>Row Details</th>
            </tr>
        </thead>
        <tbody>
    `;

    selectedIndexes.forEach((index, i) => {
        let r: any = selectedRecords[i] || {};
        html += `
        <tr>
            <td>${index.rowIndex}</td>
            <td>${index.cellIndexes.join(', ')}</td>
            <td>
                <table style="width:100%;border-collapse:collapse">
                    <tr><td><b>Task ID:</b></td><td>${r.TaskID}</td></tr>
                    <tr><td><b>Task Name:</b></td><td>${r.TaskName}</td></tr>
                    <tr><td><b>Start Date:</b></td><td>${r.StartDate ? new Date(r.StartDate).toDateString() : ''}</td></tr>
                    <tr><td><b>Duration:</b></td><td>${r.Duration}</td></tr>
                    <tr><td><b>Progress:</b></td><td>${r.Progress}%</td></tr>
                </table>
            </td>
        </tr>`;
    });

    html += '</tbody></table>';

    container.innerHTML = html;
    dialogObj.show();
});
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <div style="padding:10px">
            <button id="showDetails">Show Selected Cell Details</button>
            <div id="Gantt"></div>
        </div>
        <div id="Dialog">
            <div id="details-container" style="max-height:240px;overflow-y:auto;padding-right:10px">
            </div>
        </div>
    </div>
</body>

</html>

Customize cell selection action

While selecting a cell in Gantt, the cellSelecting and cellSelected event will be triggered. The cellSelecting event will be triggered on initialization of cell selection action, and you can get the current selecting cell information to prevent the selection of a particular cell in a particular row. The cellSelected event will be triggered on completion of cell selection action, and you can get the current selected cell’s information. The following code example demonstrates how to prevent the selection of the cell using the cellSelecting event.

import { Gantt, Selection, CellSelectingEventArgs, CellSelectEventArgs, CellDeselectEventArgs } from '@syncfusion/ej2-gantt';
import { GanttData } from './datasource.ts';

Gantt.Inject(Selection);

let gantt: Gantt = new Gantt({
    dataSource: GanttData,
    height: '370px',
    enableHover: false,
    taskFields: {
        id: 'TaskID',
        name: 'TaskName',
        startDate: 'StartDate',
        endDate: 'EndDate',
        duration: 'Duration',
        progress: 'Progress',
        parentID: 'ParentID'
    },
    selectionSettings: {
        mode: 'Cell',
        type: 'Single'
    },
    cellSelecting: (args: CellSelectingEventArgs) => {
        updateMessage('Trigger cellSelecting');
        if ((args.data as any).TaskName === 'Perform Soil test') {
            args.cancel = true;
            updateMessage('Trigger cellSelecting - Selection canceled for "Perform Soil test"');
        }
    },
    cellSelected: (args: CellSelectEventArgs) => {
        updateMessage('Trigger cellSelected');
        (args.currentCell as HTMLElement).style.backgroundColor = 'rgb(96, 158, 101)';
    },
    cellDeselecting: (args: CellDeselectEventArgs) => {
        updateMessage('Trigger cellDeselecting');
        if (args.cells && args.cells.length > 0) {
            (args.cells[0] as HTMLElement).style.color = 'rgb(253, 253, 253)';
        }
    },
    cellDeselected: (args: CellDeselectEventArgs) => {
        updateMessage('Trigger cellDeselected');
        if (args.cells && args.cells.length > 0) {
            (args.cells[0] as HTMLElement).style.backgroundColor = 'rgb(245, 69, 69)';
        }
    }
});

gantt.appendTo('#Gantt');

function updateMessage(text: string): void {
    const msgEl: HTMLElement | null = document.getElementById('message');
    if (msgEl) {
        msgEl.innerText = text;
        msgEl.style.display = 'block';
    }
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Gantt</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript Gantt Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="index.css" rel="stylesheet" />
	<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='loader'>Loading....</div>
    <div id='container'>
        <p id="message" style="color:red; text-align: center;"></p>
        <div id='Gantt'></div>        
    </div>
</body>

</html>

Limitations for cell selection

  • Cell-based selection is not supported when virtualization is enabled.