
Syncfusion Angular Gantt Chart
- 213 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-gantt-chart for development tasks
About
syncfusion-angular-gantt-chart: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-gantt-chart
Syncfusion Angular Gantt Chart by the numbers
- 213 all-time installs (skills.sh)
- +12 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,894 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/angular-ui-components-skills --skill syncfusion-angular-gantt-chartAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 213 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-gantt-chart for development tasks
Files
Syncfusion Angular Gantt Chart
A comprehensive skill for implementing and configuring the Syncfusion Angular Gantt Chart component (ejs-gantt). This covers everything from initial setup through advanced features like critical path, virtual scrolling, resource views, undo/redo, state persistence, localization, and export.
When to Use This Skill
Use this skill when you need to:
- Install and set up the Angular Gantt Chart component
- Bind local or remote data to the Gantt chart
- Configure task scheduling modes (Auto/Manual/Custom)
- Define task dependencies and predecessor relationships
- Add, edit, or delete tasks (cell, dialog, taskbar editing)
- Assign and manage resources
- Configure timelines, zooming, and tier formats
- Customize taskbars, labels, and data markers
- Filter, sort, search, or select rows/cells
- Enable toolbar, context menu, or undo/redo
- Export to Excel or PDF
- Implement virtual scrolling or state persistence
- Apply localization, RTL layout, or timezone configuration
- Work with holidays, event markers, critical path, or baseline
---
Documentation and Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation via
ng add @syncfusion/ej2-angular-gantt - CSS imports for all themes (material3, bootstrap5, fluent2, tailwind3)
- Setting up Angular standalone component with
importsandproviders - Binding data with
dataSourceandtaskFields— self-referential vs hierarchical - Injecting feature services (EditService, FilterService, ToolbarService, etc.)
- Configuring timeline, toolbar, editing, filtering, sorting
gridLinesvalues:'Both'|'Horizontal'|'Vertical'|'None'actionFailureerror handling for common configuration mistakes
Data Binding
📄 Read: references/data-binding.md
- Default pattern: Self-referential flat array with
id+parentID(idMapping + parentIdMapping) — use this unless user explicitly asks for nested data - Hierarchical local data with
childarray — only when user explicitly requests nested/tree structure - Decision table: when to use self-referential vs hierarchical
- Remote data binding with
DataManagerand adaptors (ODataV4, WebApiAdaptor, UrlAdaptor) - Load-on-demand (virtual loading) with
loadChildOnDemandandhasChildMapping - Observable / RxJS data binding with
asyncpipe - Remote CRUD with
crudUrl,insertUrl,updateUrl,removeUrl,batchUrl - Common gotchas table (missing
isPrimaryKey, wrong adaptor, parent date issues)
Task Scheduling
📄 Read: references/task-scheduling.md
taskMode:'Auto'(default),'Manual','Custom'(per-task via boolean field)- Auto mode: dates calculated from dependencies, working time, and holidays
- Manual mode: all dates fixed as-is in data source; use
validateManualTasksOnLinkingto still adjust on link - Custom mode: per-task scheduling via mapped boolean field in data source
- Unscheduled tasks (
allowUnscheduledTasks) — partial dates, floating bars durationUnit:'Day'|'Hour'|'Minute'- Working days:
workWeekarray (default Mon–Fri);includeWeekend: truemakes all 7 days working - Working hours:
dayWorkingTime— array of{ from, to }ranges (default 8–17); affects hour-based durations - Baseline dates (
renderBaseline,baselineStartDate,baselineEndDate,baselineColor) - Work scheduling (effort-driven) with
workfield andworkUnit
Task Dependencies
📄 Read: references/task-dependencies.md
- Dependency types:
FS(Finish-to-Start),SS,FF,SF— format:'2FS','3SS+1d' - Comma-separated multiple predecessors:
'2FS,3SS' - Predecessor lag/lead offsets with
d/h/munits autoUpdatePredecessorOffset— sync offset values with actual positions on loadallowParentDependency— enable parent-child and cross-hierarchy dependencies- Editing via connector line drag when
editSettings.allowTaskbarEditing: true actionBeginrequestType: 'validateLinkedTask'— handle dependency conflicts- Programmatic:
addPredecessor(),removePredecessor(),updateRecordById() connectorLineWidthandconnectorLineBackgroundfor connector styling
Task Constraints
📄 Read: references/task-constraints.md
- 8 constraint types: ASAP (0), ALAP (1), MSO (2), MFO (3), SNET (4), SNLT (5), FNET (6), FNLT (7)
- Map via
taskFields.constraintType(numeric) andtaskFields.constraintDate(Date) - Constraints enforced only in Auto mode; stored-but-passive in Manual mode
- Conflicts with dependencies surface in
actionBeginevent
Managing Tasks
📄 Read: references/managing-tasks.md
editSettings:allowEditing,allowAdding,allowDeleting,allowTaskbarEditing,mode('Auto'|'Dialog')- Cell editing with
editTypeper column:'numericedit','defaultedit','dropdownedit','booleanedit','datepickeredit' - Dialog editing with custom tab configuration (
addDialogFields,editDialogFields) - Programmatic:
addRecord(),updateRecordById(),deleteRecord(),openAddDialog(),openEditDialog(id) - Expand/collapse:
expandAll(),collapseAll(),expandByID(id),collapseByID(id); events:expanding,expanded,collapsing,collapsed - Validation via
actionBeginevent (args.cancel = trueto block) - Server CRUD via
actionComplete+requestTypeinspection - Indent / outdent hierarchy changes via toolbar or
indent()/outdent()methods
Splitting and Merging Tasks
📄 Read: references/splitting-and-merging.md
taskFields.segmentsfor hierarchical data;taskFields.segmentIdfor self-referential data- Split at load time or dynamically via dialog Segments tab or context menu
SplitTask - Merge via context menu
MergeTaskor by dragging segments together onTaskbarClickwithsegmentIndexto detect which segment was clicked- Limitations: no splits on parent/milestone tasks; incompatible with multi-taskbar resource view
Resources
📄 Read: references/resources.md
resources(data) +resourceFields(field mapping:id,name,unit,group)taskFields.resourceInfoto link resources to tasks- Resource view mode (
viewType: 'ResourceView') with row-per-resource display showOverAllocationAsMultiTaskbar— stacked taskbars for over-allocated resourcesallowTaskbarOverlap— controls overlapping vs stacked taskbars in resource rows (and affects same-resource dependency rendering)- Work-based scheduling:
workfield,taskType('FixedWork','FixedDuration','FixedUnit') - Work unit:
workUnit: 'Hour'|'Day'|'Minute'
Columns
📄 Read: references/columns.md
- Column
field,headerText,width,format,type,template,headerTemplate - Column reordering (
allowReordering), resizing (allowResizing) - Frozen columns (
freeze: 'Left'|'Right') — requiresFreezeService - Column spanning via
queryCellInfo treeColumnIndexfor tree expand/collapse column- WBS (Work Breakdown Structure) column with
columnType: 'WBS' - Column menu (
showColumnMenu) — sort, filter, auto-fit, column chooser isPrimaryKeyrequirement for CRUD operations
Timeline
📄 Read: references/timeline.md
timelineSettingsconfiguration- Top tier and bottom tier customization
- Timeline view modes (day/week/month/year)
- Formatter function with
(date, format, tier, mode)parameters - Timeline cell width (
timelineUnitSize) - Custom date formats
projectStartDateandprojectEndDate- Timeline view window (
viewStartDate/viewEndDate) - Week start day (
weekStartDay) - Automatic timescale update (
updateTimescaleView) - Weekend highlighting (
timelineSettings.showWeekend) - Timeline cells tooltip (
showTooltip) timelineTemplate— custom HTML in tier header cells (via<ng-template #timelineTemplate let-data>usingdata.date,data.value,data.tier)- Navigate timeline (
previousTimeSpan()/nextTimeSpan()) - Zooming in and out
Taskbar
📄 Read: references/taskbar.md
taskbarTemplate,parentTaskbarTemplate,milestoneTemplate— full custom templateslabelSettings:leftLabel,rightLabel,taskLabel(field names or templates)queryTaskbarInfo— dynamic styling:taskbarBgColor,progressBarBgColor,taskbarBorderColorindicators/ data markers on individual tasks:date,iconClass,label,tooltip- Tooltip customization via
tooltipSettings.taskbartemplate taskbarHeight,taskbarCornerRadius,allowTaskbarDragAndDrop
Filtering and Searching
📄 Read: references/filtering-and-searching.md
allowFiltering: true+FilterService— menu and Excel filter typesfilterSettings.type:'Menu'(default) |'Excel'filterSettings.hierarchyMode:'Parent'|'Child'|'Both'|'None'- Initial filter on load via
filterSettings.columnsarray - Searching:
allowSearching: true+'Search'in toolbar searchSettings:fields,operator,ignoreCase- Programmatic:
filterByColumn(),clearFiltering(),search()
Sorting
📄 Read: references/sorting.md
allowSorting: true+SortService— click column headers to sort- Disable per column:
{ field: 'TaskID', allowSorting: false } - Multi-column sort: Ctrl+click additional headers; Shift+click to remove
- Initial sort on load via
sortSettings.columnsarray - Programmatic:
sortColumn(),removeSortColumn(),clearSorting()
Rows
📄 Read: references/rows.md
rowDataBound/queryCellInfo— dynamic row/cell stylingrowHeight— uniform row height in pixels (must exceedtaskbarHeight)rowSpanviaqueryCellInfo— vertical cell spanningallowRowDragAndDrop— drag rows to reorder/reparent;rowDropeventsindent()/outdent()— change hierarchy level for the selected rowautoFocusTasks— focus the matching taskbar when a row is selected
Selection
📄 Read: references/selection.md
allowSelection: true+SelectionService— required for any selection featureselectionSettings.mode:'Row'(default) |'Cell'|'Both'selectionSettings.type:'Single'(default) |'Multiple'(Ctrl+click for multi-select)selectionSettings.enableToggle— click to deselect already-selected row- Cell selection modes:
'Flow'|'Box'|'BoxWithBorder' - Programmatic:
selectRow(),selectRows(),selectCell(),clearSelection(),getSelectedRecords()
Scrolling
📄 Read: references/scrolling.md
enableVirtualization: true+VirtualScrollService— DOM virtualization for large datasetsenableTimelineVirtualization— virtualize timeline columns independently- Splitter:
splitterSettings.position(percentage string or pixel value),columnIndex,view('Default'|'Grid'|'Chart') - Programmatic:
scrollToDate('04/02/2024'),scrollToTaskbar(taskId) - Virtual scroll limitations: row/column templates, grouping, and some aggregate features not supported
Toolbar
📄 Read: references/toolbar.md
ToolbarServicerequired; settoolbaras string array or mixedItemModelarray- Built-in items:
'Add','Edit','Delete','Update','Cancel','ExpandAll','CollapseAll','Search','Indent','Outdent','ZoomIn','ZoomOut','ZoomToFit','ExcelExport','CsvExport','PdfExport','CriticalPath','Undo','Redo','SplitTask','MergeTask','ColumnChooser' - Custom items via
ItemModel:text,id,prefixIcon,align,tooltipText { type: 'Separator' }for visual dividerstoolbarClickevent — useargs.item.idto identify clicked item (format:'{ganttId}_{itemId}')- Enable/disable programmatically:
enableToolbarItems()/disableToolbarItems()
Programmatic Methods
📄 Read: references/gantt-methods.md
- Column utilities:
autoFitColumns() - Edit control:
cancelEdit(),openAddDialog(),openEditDialog() - Task management:
deleteRecord(),convertToMilestone(),changeTaskMode(),updateRecordByID(),updateRecordByIndex(),updateTaskId(),updateDataSource(),updateProjectDates() - Toolbar control:
enableItems() - Expand/Collapse:
expandByIndex(),collapseByIndex() - Undo/Redo stacks:
clearUndoCollection(),clearRedoCollection(),getUndoActions(),getRedoActions() - Data retrieval:
getCurrentViewData(),getRecordByID(),getTaskByUniqueID(),getTaskInfo(),getTaskbarHeight(),getExpandedRecords(),getGanttColumns(),getGridColumns() - Formatting helpers:
getDurationString(),getWorkString() - DOM access:
getRowByID(),getRowByIndex() - Sorting:
removeSortColumn() - Selection:
selectCells() - Row reorder:
reorderRows() - Scrolling:
scrollToTask(),updateChartScrollOffset()
Events
📄 Read: references/events.md
- Lifecycle:
load,created,dataBound,destroyed - Edit lifecycle:
actionBegin(cancel withargs.cancel = true),actionComplete,actionFailure - Taskbar:
taskbarEditing,taskbarEdited,onTaskbarClick,queryTaskbarInfo - Row/cell:
rowDataBound,queryCellInfo,rowSelected,rowDeselected,cellSelected - Expand/collapse:
expanding,expanded,collapsing,collapsed - Export:
beforeExcelExport,excelExportComplete,beforePdfExport,pdfExportComplete,pdfQueryTaskbarInfo recordDoubleClick— open custom edit on double click
Context Menu
📄 Read: references/context-menu.md
enableContextMenu: true+ContextMenuService— right-click on rows or header- Default items include:
'AutoFitAll','AutoFit','SortAscending','SortDescending','Add','Edit','Delete','Save','Cancel','Indent','Outdent','TaskInformation','SplitTask','MergeTask' - Custom items via
ContextMenuItemModel:text,id,iconCss,target(row/header) contextMenuOpen— dynamically hide/show items per rowcontextMenuClick— handle item selection
Holidays and Event Markers
📄 Read: references/holidays-and-markers.md
DayMarkersServicerequired for both holidays and event markersholidays: array of{ from, to?, label, cssClass }— non-working days that extend task durationseventMarkers: array of{ day, label, cssClass, top? }— full-height vertical lines at specific dates- Custom styling per type via
cssClass+ CSS targeting.e-gantt-event-marker/.e-span-label topproperty staggers overlapping markers at the same date
Critical Path
📄 Read: references/critical-path.md
enableCriticalPath: true+CriticalPathService— highlights zero/negative-slack tasks in red'CriticalPath'toolbar item — user toggle buttongetCriticalTasks()— returns array ofIGanttDataobjects withslackvaluequeryTaskbarInfo+ganttProperties.isCritical— conditional per-task coloring- CSS overrides:
.e-critical-path-container,.e-critical-connector-line - Rules: completed tasks (100%) excluded; parent/child criticality independent; auto-recalculates on any change
Export (Excel and PDF)
📄 Read: references/export.md
- Excel:
allowExcelExport: true+ExcelExportService; callexcelExport()/csvExport() - PDF:
allowPdfExport: true+PdfExportService; callpdfExport() ExcelExportProperties:fileName,dataSource,includeHiddenColumn,header,footerPdfExportProperties:fileName,pageOrientation,pageSize,fitToWidthSettings,ganttStyle,theme- PDF header/footer content types:
Text,Line,PageNumber,Image - Single-page export:
fitToWidthSettings.isFitToWidth: true - Blob export:
pdfExport({}, true)→ blob available inpdfExportCompleteevent - Multi-Gantt export to one PDF via chained
pdfExport()withmultipleExport pdfQueryTaskbarInfo— per-taskbar colors in PDF output
Undo / Redo
📄 Read: references/undo-redo.md
enableUndoRedo: true+UndoRedoService— up to 10 steps by defaultundoRedoActionsarray — choose which action types are tracked (18 supported actions)undoRedoStepsCount— configure history depth- Keyboard:
Ctrl+Z/Ctrl+Y; programmatic:undo()/redo() 'Undo'/'Redo'toolbar items auto-disable when history is exhausted
State Persistence
📄 Read: references/state-persistence.md
enablePersistence: true— saves filter/sort/column state tolocalStorageunder key'{id}gantt'- Requires unique
idon<ejs-gantt>element - Reset methods:
clearStorage(), remove localStorage key manually, or set newid - Immutable mode (
enableImmutableMode) — only re-renders changed rows for large-dataset performance - Loading animation:
loadingIndicator.indicatorType—'Spinner'(default) |'Shimmer' - Manual spinner:
showSpinner()/hideSpinner()
Localization, RTL and Formatting
📄 Read: references/localization-rtl.md
localeproperty +setCulture()+L10n.load()— translate all Gantt UI strings- Full locale key reference for the
'gantt'namespace - RTL:
[enableRtl]="true"+locale="ar"— reverses layout direction timezone— IANA timezone string (e.g.'America/New_York','UTC') for consistent cross-region dates- Column date formatting:
formatstring or{ type: 'date', skeleton: 'yMd' } - Column number formatting:
'N2','C2','P1'etc.
---
Quick Start Example
import { Component } from '@angular/core';
import { GanttModule, EditService, SortService, FilterService, ToolbarService, SelectionService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
standalone: true,
providers: [EditService, SortService, FilterService, ToolbarService, SelectionService],
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskFields"
[height]="'450px'"
[toolbar]="toolbar"
[allowFiltering]="true"
[allowSorting]="true"
[editSettings]="editSettings">
</ejs-gantt>
`
})
export class AppComponent {
// Default: self-referential data (flat array with id + parentID)
// Use hierarchical (child array) only if user explicitly requests it
public data: object[] = [
{ TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2024'), Duration: 5, Progress: 0, ParentID: null },
{ TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50, ParentID: 1 },
{ TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50, ParentID: 1 },
{ TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50, ParentID: 1, Predecessor: '3FS' }
];
public taskFields: object = {
id: 'TaskID', // idMapping
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
parentID: 'ParentID' // parentIdMapping — null = root task
};
public toolbar: string[] = ['Add', 'Edit', 'Delete', 'ExpandAll', 'CollapseAll', 'Search'];
public editSettings: object = { allowEditing: true, allowAdding: true, allowDeleting: true, allowTaskbarEditing: true };
}---
Common Patterns
When user needs task editing
→ Set editSettings.allowEditing: true, inject EditService → Use mode: 'Auto' for cell editing, mode: 'Dialog' for dialog
When user needs large dataset performance
→ Read references/scrolling.md — enable enableVirtualization: true + VirtualScrollService
When user needs to export data
→ Read references/export.md — inject ExcelExportService or PdfExportService
When user needs resource management
→ Read references/resources.md — configure resources + resourceFields
When user needs undo/redo
→ Read references/undo-redo.md — inject UndoRedoService, set enableUndoRedo: true
When user needs localization or RTL
→ Read references/localization-rtl.md — call L10n.load() before bootstrap, set locale and enableRtl
When user needs state persistence
→ Read references/state-persistence.md — set enablePersistence: true and unique id
When user needs split/segment tasks
→ Read references/splitting-and-merging.md — map taskFields.segments, inject EditService
---
Key Module Injections
| Feature | Service to Inject |
|---|---|
| Editing (add/edit/delete/taskbar drag) | EditService |
| Filtering | FilterService |
| Sorting | SortService |
| Toolbar | ToolbarService |
| Selection | SelectionService |
| Day Markers / Holidays / Event Markers | DayMarkersService |
| Critical Path | CriticalPathService |
| Excel / CSV Export | ExcelExportService |
| PDF Export | PdfExportService |
| Undo / Redo | UndoRedoService |
| Column Menu | ColumnMenuService |
| Context Menu | ContextMenuService |
| Virtual Scrolling | VirtualScrollService |
| Row Drag and Drop | RowDDService |
| Column Reordering | ReorderService |
| Frozen Columns | FreezeService |
| Column Resizing | ResizeService |
---
Key Props Reference
| Property | Type | Default | Description |
|---|---|---|---|
dataSource | object[] \ | DataManager | [] |
taskFields | TaskFieldsModel | — | Maps data fields to Gantt task properties |
height | string \ | number | 'auto' |
taskMode | string | 'Auto' | Scheduling mode: 'Auto' \ |
editSettings | EditSettingsModel | — | Enable add/edit/delete/taskbar editing and edit mode |
toolbar | string[] \ | ItemModel[] | — |
allowFiltering | boolean | false | Enable column filter menus — requires FilterService |
filterSettings | FilterSettingsModel | — | type, hierarchyMode, columns (initial filters) |
allowSorting | boolean | false | Enable column sorting — requires SortService |
sortSettings | SortSettingsModel | — | columns array for initial sort on load |
allowSelection | boolean | true | Enable row/cell selection — requires SelectionService |
selectionSettings | SelectionSettingsModel | — | mode, type, enableToggle, cellSelectionMode |
enableCriticalPath | boolean | false | Highlight critical path — requires CriticalPathService |
enableUndoRedo | boolean | false | Enable undo/redo — requires UndoRedoService |
undoRedoActions | string[] | (all actions) | Which action types to track in history |
undoRedoStepsCount | number | 10 | Maximum undo/redo history depth |
enablePersistence | boolean | false | Persist filter/sort/column state to localStorage |
enableImmutableMode | boolean | false | Re-render only changed rows on data refresh |
allowExcelExport | boolean | false | Enable Excel export — requires ExcelExportService |
allowPdfExport | boolean | false | Enable PDF export — requires PdfExportService |
enableContextMenu | boolean | false | Enable right-click context menu — requires ContextMenuService |
contextMenuItems | string[] \ | ContextMenuItemModel[] | (defaults) |
enableVirtualization | boolean | false | DOM virtualization for large datasets — requires VirtualScrollService |
enableTimelineVirtualization | boolean | false | Virtualize timeline columns |
renderBaseline | boolean | false | Show baseline bars alongside current taskbars |
baselineColor | string | 'red' | Baseline bar color |
allowUnscheduledTasks | boolean | false | Allow tasks missing start/end/duration |
validateManualTasksOnLinking | boolean | false | Adjust manual task dates when dependency links change |
allowParentDependency | boolean | true | Allow dependencies between parent/child tasks |
autoUpdatePredecessorOffset | boolean | false | Sync predecessor offsets with actual positions on load |
highlightWeekends | boolean | false | Shade weekend columns in timeline |
gridLines | string | 'Both' | Grid lines: 'Both' \ |
rowHeight | number | 36 | Height of each row in pixels |
allowRowDragAndDrop | boolean | false | Drag rows to reorder or reparent |
showColumnMenu | boolean | false | Column header context menu — requires ColumnMenuService |
timelineSettings | TimelineSettingsModel | — | topTier, bottomTier, timelineUnitSize, weekStartDay |
timelineViewMode | string | — | Shortcut: 'Hour' \ |
projectStartDate | Date \ | string | (from data) |
projectEndDate | Date \ | string | (from data) |
holidays | HolidayModel[] | [] | Non-working days with labels — requires DayMarkersService |
eventMarkers | EventMarkerModel[] | [] | Vertical marker lines — requires DayMarkersService |
resources | object[] | — | Resource data array |
resourceFields | ResourceFieldsModel | — | Maps resource id, name, unit, group fields |
locale | string | 'en-US' | Culture code for localization (e.g. 'fr', 'ar') |
enableRtl | boolean | false | Right-to-left layout |
timezone | string | (browser) | IANA timezone (e.g. 'UTC', 'America/New_York') |
durationUnit | string | 'Day' | Default duration unit: 'Day' \ |
workUnit | string | 'Hour' | Work scheduling unit: 'Hour' \ |
workWeek | string[] | Mon–Fri | Working days: ['Monday','Tuesday','Wednesday','Thursday','Friday'] |
includeWeekend | boolean | false | Treat all 7 days as working days |
dayWorkingTime | object[] | [{from:8,to:17}] | Working hour ranges per day: [{ from: 8, to: 12 }, { from: 13, to: 17 }] |
dateFormat | string | 'MM/dd/yyyy' | Global date display format for all date columns |
splitterSettings | SplitterSettingsModel | — | position, columnIndex, view for TreeGrid/chart split |
loadingIndicator | LoadingIndicatorModel | — | indicatorType: 'Spinner' \ |
Columns in Angular Gantt Chart
Table of Contents
- Column Definition
- Column Types
- Column Headers and Formatting
- Column Template
- Column Reordering
- Column Resizing
- Frozen Columns
- Column Spanning
- Tree Column Configuration
- WBS Column
- Column Menu
- Column Rendering Options
---
Column Definition
Columns are defined in the columns array. Each column maps a data field and defines display behavior:
public columns: object[] = [
{ field: 'TaskID', headerText: 'ID', width: 60, isPrimaryKey: true },
{ field: 'TaskName', headerText: 'Task Name', width: 250, clipMode: 'EllipsisWithTooltip' },
{ field: 'StartDate', headerText: 'Start', format: 'MM/dd/yyyy' },
{ field: 'Duration', headerText: 'Duration', textAlign: 'Right' },
{ field: 'Progress', headerText: 'Progress (%)', textAlign: 'Right' },
{ field: 'Verified', headerText: 'Verified', type: 'boolean', displayAsCheckBox: true }
];---
Column Types
| Type | Description |
|---|---|
'string' | Default; text data |
'number' | Numeric with formatting support |
'boolean' | True/false; can render as checkbox |
'date' | Date values |
'datetime' | Date and time values |
'checkbox' | Dedicated checkbox column |
{ field: 'Verified', type: 'boolean', displayAsCheckBox: true }---
Column Headers and Formatting
{
field: 'StartDate',
headerText: 'Start Date', // Column header label
format: { type: 'date', format: 'MM/dd/yyyy' }, // Date format
textAlign: 'Center', // 'Left' | 'Right' | 'Center' | 'Justify'
headerTextAlign: 'Center',
width: 120,
minWidth: 80,
maxWidth: 300
}For number columns:
{ field: 'Progress', format: 'N0', textAlign: 'Right' } // No decimal places---
Column Template
Customize how cell values are displayed using Angular templates:
@Component({
template: `
<ejs-gantt [columns]="columns">
<ng-template #progressTemplate let-data>
<div class="progress-bar">
<div [style.width.%]="data.Progress" class="fill"></div>
<span>{{data.Progress}}%</span>
</div>
</ng-template>
</ejs-gantt>
`
})public columns: object[] = [
{ field: 'Progress', headerText: 'Progress', template: '#progressTemplate' }
];---
Column Reordering
Allow users to drag columns to change their order:
<ejs-gantt [allowReordering]="true"></ejs-gantt>Programmatic reorder:
this.ganttObj.reorderColumns('TaskName', 'Duration'); // Move TaskName before Duration---
Column Resizing
Allow users to resize columns by dragging column borders:
<ejs-gantt [allowResizing]="true"></ejs-gantt>Set min/max widths to control resize bounds:
{ field: 'TaskName', minWidth: 120, maxWidth: 400 }Auto-fit a column width to content:
this.ganttObj.autoFitColumns(['TaskName', 'Duration']);---
Frozen Columns
Keep columns visible when scrolling horizontally. Set frozenColumns to the number of columns to freeze from the left:
<ejs-gantt [frozenColumns]="2"></ejs-gantt>Or freeze at column level:
{ field: 'TaskID', isFrozen: true }Use the column.freeze property to freeze columns in specific directions:
public columns: object[] = [
{ field: 'TaskID', headerText: 'ID', freeze: 'Left' },
{ field: 'TaskName', headerText: 'Task Name' },
{ field: 'Progress', headerText: 'Progress', freeze: 'Fixed' },
{ field: 'Status', headerText: 'Status', freeze: 'Right' }
];The freeze property supports: Left | Right | Fixed. The frozen column and scrollable section behave as independent scroll areas.
Note: The freeze property is not compatible with isFrozen and frozenColumns.
---
Column Spanning
Merge cells across multiple rows in the header:
public splitterSettings: object = { columnIndex: 3 };
// Column spanning in header
public columns: object[] = [
{ field: 'TaskID', headerText: 'ID' },
{ field: 'TaskName', headerText: 'Task Name' },
{ field: 'StartDate', headerText: 'Start' },
{ field: 'EndDate', headerText: 'End' }
];Use queryCellInfo to span data cells:
public queryCellInfo(args: any): void {
if (args.column.field === 'StartDate' && args.data.TaskID === 1) {
args.colSpan = 2; // Merge this cell with the next column
}
}---
Tree Column Configuration
The tree column (expand/collapse hierarchy) is typically the TaskName column. Configure with treeColumnIndex:
<ejs-gantt [treeColumnIndex]="1"></ejs-gantt>treeColumnIndex is zero-based. Default is 0 (first column).
---
WBS Column
Work Breakdown Structure (WBS) column shows hierarchical numbering (1, 1.1, 1.1.1, etc.):
public columns: object[] = [
{ field: 'TaskID', headerText: 'ID' },
{ field: 'TaskName', headerText: 'Task Name' },
{ field: 'wbs', headerText: 'WBS' } // Built-in WBS field
];The wbs field is auto-generated by the Gantt based on task hierarchy.
---
Column Menu
Add a context menu to column headers (sort, filter, autofit, hide):
<ejs-gantt [showColumnMenu]="true"></ejs-gantt>Inject ColumnMenuService. Available menu items: SortAscending, SortDescending, AutoFitAll, AutoFit, Filter.
Customize items per column:
{ field: 'TaskName', showColumnMenu: false } // Disable menu for this column---
Column Rendering Options
{
field: 'TaskName',
visible: true, // Show/hide column
allowEditing: true, // Allow editing this column
allowSorting: true, // Allow sorting by this column
allowFiltering: true, // Allow filtering this column
allowResizing: true, // Allow resizing this column
allowReordering: true, // Allow reordering this column
disableHtmlEncode: false, // Allow HTML in cell content
clipMode: 'EllipsisWithTooltip' // Handle overflow: 'Clip' | 'Ellipsis' | 'EllipsisWithTooltip'
}Toggle column visibility programmatically:
this.ganttObj.hideColumn('TaskName', 'headerText');
this.ganttObj.showColumn('TaskName', 'headerText');Context Menu in Syncfusion Angular Gantt Chart
Table of Contents
- Enabling context menu
- Default context menu items
- Custom context menu items
- contextMenuOpen event
- contextMenuClick event
- Item visibility by target
---
Enabling context menu
Set enableContextMenu to true and inject ContextMenuService in the component's providers:
import { GanttModule, ContextMenuService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [ContextMenuService],
standalone: true,
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskSettings"
[enableContextMenu]="true"
[editSettings]="editSettings">
</ejs-gantt>
`
})
export class AppComponent { }Context menu items are automatically shown/hidden based on the clicked target (header vs. row) and the current editSettings configuration.---
Default context menu items
| Item | Description | Appears on |
|---|---|---|
AutoFit | Fits clicked column to content width | Column header |
AutoFitAll | Fits all columns to content | Column header |
SortAscending | Sorts column ascending | Column header |
SortDescending | Sorts column descending | Column header |
TaskInformation | Opens task edit dialog | Task row |
Add | Inserts a new task (sub-menu: Above, Below, Child, Milestone) | Task row |
Indent | Moves task one level inward | Task row |
Outdent | Moves task one level outward | Task row |
DeleteTask | Deletes selected task | Task row |
Save | Saves current cell edit | Task row (editing) |
Cancel | Cancels current cell edit | Task row (editing) |
SplitTask | Splits task at clicked date | Task row |
MergeTask | Merges split segments (sub-menu: Left, Right) | Split task row |
Convert | Converts task (sub-menu: To Milestone, To Task) | Task row |
DeleteDependency | Deletes dependency of selected task | Connector line |
Items that require disabled features (e.g.,AddwithoutallowAdding) will be automatically disabled or hidden.
---
Custom context menu items
Use the contextMenuItems property to add custom items alongside or instead of defaults. Items use ContextMenuItemModel format:
import { ContextMenuItemModel } from '@syncfusion/ej2-angular-grids';
@Component({
template: `
<ejs-gantt
[contextMenuItems]="contextMenuItems"
(contextMenuClick)="contextMenuClick($event)">
</ejs-gantt>
`
})
export class AppComponent {
public contextMenuItems: (string | ContextMenuItemModel)[] = [
'TaskInformation',
'DeleteTask',
{ id: 'markComplete', text: 'Mark as Complete', target: '.e-content', iconCss: 'e-icons e-check' },
{ id: 'hideCol', text: 'Hide Column', target: '.e-gridheader', iconCss: 'e-icons e-hide' }
];
}ContextMenuItemModel properties
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for the item |
text | string | Display label |
target | string | CSS selector: .e-content for rows, .e-gridheader for headers |
iconCss | string | CSS class for icon (e.g., e-icons e-check) |
items | object[] | Sub-menu items |
disabled | boolean | Whether item is initially disabled |
separator | boolean | Set true to render as a divider line |
---
contextMenuOpen event
Fires before the context menu is displayed. Use to dynamically show/hide items:
import { BeforeOpenCloseMenuEventArgs } from '@syncfusion/ej2-angular-navigations';
public contextMenuOpen(args: BeforeOpenCloseMenuEventArgs & { rowInfo?: any }): void {
// Hide 'markComplete' for already-complete tasks
if (args.rowInfo?.rowData) {
const progress = (args.rowInfo.rowData as any).taskData?.Progress;
if (progress === 100) {
const item = args.element.querySelector('#markComplete');
if (item) {
(item as HTMLElement).style.display = 'none';
}
}
}
}---
contextMenuClick event
Fires when a context menu item is clicked. The args object includes item id, text, and row data:
import { MenuEventArgs } from '@syncfusion/ej2-angular-navigations';
public contextMenuClick(args: MenuEventArgs): void {
if (args.item.id === 'markComplete') {
const rowData = (args as any).rowInfo?.rowData;
if (rowData) {
// Update task progress to 100
this.ganttObj!.updateRecordByID({
...rowData.taskData,
Progress: 100
});
}
}
if (args.item.id === 'hideCol') {
const col = (args as any).column?.field;
if (col) {
this.ganttObj!.hideColumn(col);
}
}
}---
Item visibility by target
The target property on custom items controls where they appear:
target value | Item appears when right-clicking on |
|---|---|
.e-content | Task rows (grid content area) |
.e-gridheader | Column header cells |
.e-chart-row | Chart/taskbar area |
| (omit target) | Appears in all contexts |
Full example
import { Component, ViewChild } from '@angular/core';
import { GanttModule, GanttComponent, ContextMenuService } from '@syncfusion/ej2-angular-gantt';
import { ContextMenuItemModel } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [GanttModule],
providers: [ContextMenuService],
standalone: true,
selector: 'app-root',
template: `
<ejs-gantt #gantt
[dataSource]="data"
[taskFields]="taskSettings"
[enableContextMenu]="true"
[editSettings]="editSettings"
[contextMenuItems]="contextMenuItems"
(contextMenuClick)="onContextMenuClick($event)">
</ejs-gantt>
`
})
export class AppComponent {
@ViewChild('gantt') public ganttObj?: GanttComponent;
public editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true
};
public contextMenuItems: (string | ContextMenuItemModel)[] = [
'TaskInformation',
'Add',
'DeleteTask',
{ separator: true },
{
id: 'expandAll',
text: 'Expand All Children',
target: '.e-content',
iconCss: 'e-icons e-expand'
}
];
public onContextMenuClick(args: any): void {
if (args.item.id === 'expandAll') {
this.ganttObj?.expandAll();
}
}
public taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
child: 'subtasks'
};
public data = [
{
TaskID: 1, TaskName: 'Planning', StartDate: new Date('2024-04-01'), EndDate: new Date('2024-04-10'),
subtasks: [
{ TaskID: 2, TaskName: 'Analysis', StartDate: new Date('2024-04-01'), Duration: 4, Progress: 50 },
{ TaskID: 3, TaskName: 'Design', StartDate: new Date('2024-04-05'), Duration: 3, Progress: 30 }
]
}
];
}Critical Path in Syncfusion Angular Gantt Chart
Table of Contents
- What is the critical path
- Setup and requirements
- Enabling critical path
- Toolbar toggle button
- Critical path calculation rules
- getCriticalTasks method
- Customizing critical path visuals
- queryTaskbarInfo with isCritical
---
What is the critical path
The critical path is the longest sequence of dependent tasks that determines the minimum project duration. Tasks on the critical path have zero or negative slack (float), meaning any delay directly impacts the overall project completion date.
The Angular Gantt Chart automatically calculates and highlights critical tasks in red with emphasized dependency connector lines.
---
Setup and requirements
Inject CriticalPathService in the component's providers:
import { GanttModule, CriticalPathService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [CriticalPathService],
standalone: true
})
export class AppComponent { }The data source must have:
- Valid
startDateandendDate(orduration) fields - Task dependency field mapped via
taskFields.dependency
---
Enabling critical path
Set enableCriticalPath to true on the <ejs-gantt> element:
@Component({
imports: [GanttModule],
providers: [CriticalPathService],
standalone: true,
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskSettings"
[enableCriticalPath]="true"
height="450px">
</ejs-gantt>
`
})
export class AppComponent {
public taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
child: 'subtasks'
};
public data = [
{
TaskID: 1, TaskName: 'Project Start', StartDate: new Date('2024-04-01'), EndDate: new Date('2024-04-21'),
subtasks: [
{ TaskID: 2, TaskName: 'Analysis', StartDate: new Date('2024-04-01'), Duration: 4, Progress: 30 },
{ TaskID: 3, TaskName: 'Design', StartDate: new Date('2024-04-01'), Duration: 4, Predecessor: '2' },
{ TaskID: 4, TaskName: 'Development', StartDate: new Date('2024-04-05'), Duration: 6, Predecessor: '3', Progress: 20 }
]
}
];
}---
Toolbar toggle button
Add 'CriticalPath' to the toolbar to allow users to toggle critical path on/off interactively:
@Component({
template: `
<ejs-gantt
[toolbar]="toolbar"
[enableCriticalPath]="true">
</ejs-gantt>
`
})
export class AppComponent {
public toolbar = ['CriticalPath', 'ZoomIn', 'ZoomOut', 'ZoomToFit'];
}---
Critical path calculation rules
| Rule | Details |
|---|---|
| Slack | Zero or negative slack = critical. Slack = task end date vs. project end date |
| Project end date | If projectEndDate is not set, the component uses the latest task end date |
| Completed tasks | Tasks with Progress === 100 are not marked critical |
| Parent vs child | Parent task criticality does NOT automatically make children critical (and vice versa); evaluated independently |
| Offset support | Dependency offsets (e.g., '2FS+3d') are factored into slack calculations |
| Manual tasks | Manual tasks compare end dates directly vs. project end date |
| Auto tasks | Use forward/backward pass (CPM) algorithm for slack |
| Recalculation | Critical path recalculates automatically when task dates, durations, dependencies, or progress change |
Dependency type impacts
| Type | Critical when |
|---|---|
| Finish-to-Start | Predecessor ends after successor should start → negative slack |
| Start-to-Start | Predecessor starts after successor should start |
| Finish-to-Finish | Timing conflict between connected tasks |
| Start-to-Finish | Timing conflict between connected tasks |
---
getCriticalTasks method
Retrieve all currently critical tasks programmatically:
import { Component, ViewChild } from '@angular/core';
import { GanttModule, GanttComponent, CriticalPathService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [CriticalPathService],
standalone: true,
template: `
<button (click)="showCriticalTasks()">Show Critical Tasks</button>
<ejs-gantt #gantt [dataSource]="data" [taskFields]="taskSettings"
[enableCriticalPath]="true">
</ejs-gantt>
`
})
export class AppComponent {
@ViewChild('gantt') public ganttObj?: GanttComponent;
public showCriticalTasks(): void {
const criticalTasks = this.ganttObj?.getCriticalTasks();
console.log('Critical tasks:', criticalTasks);
// criticalTasks is an array of IGanttData objects
criticalTasks?.forEach(task => {
console.log(task.ganttProperties.taskName, 'slack:', task.slack);
});
}
// ... taskSettings and data
}---
Customizing critical path visuals
Default rendering
By default, critical tasks render with:
- Red taskbar background
- Thicker/red connector lines between critical dependencies
CSS overrides
/* Critical taskbar color */
.e-gantt .e-critical-path-container .e-gantt-child-taskbar-inner-div {
background-color: #c0392b !important;
}
/* Critical connector line */
.e-gantt .e-critical-connector-line {
stroke: #c0392b;
stroke-width: 2px;
}
/* Critical milestone */
.e-gantt .e-critical-path-container .e-gantt-milestone {
background-color: #c0392b;
}---
queryTaskbarInfo with isCritical
Use the queryTaskbarInfo event to apply conditional styling based on whether a task is critical:
import { IQueryTaskbarInfoEventArgs } from '@syncfusion/ej2-angular-gantt';
@Component({
template: `
<ejs-gantt
[enableCriticalPath]="true"
(queryTaskbarInfo)="queryTaskbarInfo($event)">
</ejs-gantt>
`
})
export class AppComponent {
public queryTaskbarInfo(args: IQueryTaskbarInfoEventArgs): void {
// isCritical is available on ganttProperties when enableCriticalPath is true
const ganttProps = args.data.ganttProperties as any;
if (ganttProps.isCritical) {
// Critical task — apply red styling
args.taskbarBgColor = '#e74c3c';
args.progressBarBgColor = '#c0392b';
args.taskbarBorderColor = '#a93226';
} else {
// Non-critical — apply default or project-specific colors
args.taskbarBgColor = '#3498db';
args.progressBarBgColor = '#2980b9';
}
}
}TheisCriticalflag is recalculated automatically whenever task scheduling changes, soqueryTaskbarInfoalways reflects the current state.
Data Binding in Angular Gantt Chart
Table of Contents
- Overview
- Local Data — Self-Referential Structure (Default)
- Local Data — Hierarchical Structure
- Remote Data Binding
- Load-on-Demand (Virtual Loading)
- Observable Data Binding
- Handling CRUD with Remote Data
- Common Gotchas
---
Overview
The dataSource property accepts:
- A JavaScript object array (local data)
- A
DataManagerinstance (remote or local with query support)
Two data structures are supported:
- Self-referential (default) — flat array where each task has an
idand aparentIDpointing to its parent task - Hierarchical — parent tasks contain nested child arrays (use only when the user explicitly asks for hierarchical / nested data)
Default rule: Always use self-referential data binding unless the user specifically requests hierarchical data. Self-referential maps directly to database tables and is the most common real-world pattern.
---
Local Data — Self-Referential Structure (Default)
Self-referential data is a flat array where parent-child relationships are expressed using two key fields:
taskFields property | Maps to | Purpose |
|---|---|---|
id | 'TaskID' | Unique identifier for each task (idMapping) |
parentID | 'ParentID' | References the parent task's ID (parentIdMapping). Root tasks have null or 0 |
import { Component } from '@angular/core';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
standalone: true,
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskFields"
[height]="'450px'">
</ejs-gantt>
`
})
export class AppComponent {
public data: object[] = [
// Root tasks — ParentID is null (no parent)
{ TaskID: 1, TaskName: 'Project Initiation', StartDate: new Date('04/02/2024'), Duration: 5, Progress: 0, ParentID: null },
// Children of Task 1 — ParentID: 1
{ TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50, ParentID: 1 },
{ TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50, ParentID: 1 },
{ TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/04/2024'), Duration: 3, Progress: 30, ParentID: 1 },
// Root task 2
{ TaskID: 5, TaskName: 'Project Estimation', StartDate: new Date('04/08/2024'), Duration: 6, Progress: 0, ParentID: null },
// Children of Task 5 — ParentID: 5
{ TaskID: 6, TaskName: 'Develop floor plan', StartDate: new Date('04/08/2024'), Duration: 3, Progress: 50, ParentID: 5 },
{ TaskID: 7, TaskName: 'List material', StartDate: new Date('04/08/2024'), Duration: 3, Progress: 50, ParentID: 5 },
];
public taskFields: object = {
id: 'TaskID', // idMapping — unique identifier field
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
parentID: 'ParentID' // parentIdMapping — parent reference field (null = root)
};
}Key rules for self-referential data:
- Root tasks must have
ParentID: null(or0— both are treated as root) - Every
ParentIDvalue must correspond to an existingTaskIDin the same array - There is no nesting in the data — the Gantt builds the tree from the ID relationships
- Best for: database tables, REST APIs returning flat records, any backend with foreign key relationships
---
Local Data — Hierarchical Structure
Use this only when the user explicitly asks for hierarchical, nested, or tree-structured data.
Hierarchical data nests child tasks inside parent tasks using the field mapped to taskFields.child:
import { Component } from '@angular/core';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
standalone: true,
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskFields"
[height]="'450px'">
</ejs-gantt>
`
})
export class AppComponent {
public data: object[] = [
{
TaskID: 1,
TaskName: 'Project Initiation',
StartDate: new Date('04/02/2024'),
EndDate: new Date('04/21/2024'),
subtasks: [
{ TaskID: 2, TaskName: 'Identify Site location', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50 },
{ TaskID: 3, TaskName: 'Perform Soil test', StartDate: new Date('04/02/2024'), Duration: 4, Progress: 50 },
{ TaskID: 4, TaskName: 'Soil test approval', StartDate: new Date('04/04/2024'), Duration: 3, Progress: 30 }
]
},
{
TaskID: 5,
TaskName: 'Project Estimation',
StartDate: new Date('04/08/2024'),
EndDate: new Date('04/21/2024'),
subtasks: [
{ TaskID: 6, TaskName: 'Develop floor plan', StartDate: new Date('04/08/2024'), Duration: 3, Progress: 50 },
{ TaskID: 7, TaskName: 'List material', StartDate: new Date('04/08/2024'), Duration: 3, Progress: 50 }
]
}
];
public taskFields: object = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
child: 'subtasks' // Maps the nested children array field name
};
}Key rules for hierarchical data:
- Child tasks are nested inside the parent's
subtasksarray (or whichever fieldchildmaps to) parentIDis NOT used — the nesting itself defines the relationship- Best for: JSON APIs that return pre-nested structures, static project data defined inline
---
Choosing Between Self-Referential and Hierarchical
| Scenario | Use |
|---|---|
| Default / no preference stated | Self-referential (id + parentID) |
| User says "flat array", "database", "foreign key" | Self-referential |
| User says "hierarchical", "nested", "tree structure", "subtasks array" | Hierarchical (id + child) |
| Remote REST API / OData | Self-referential (most backends return flat records) |
| Static inline data with nesting | Either works — prefer self-referential |
---
Remote Data Binding
Use a DataManager with the appropriate adaptor for your backend:
import { DataManager, ODataV4Adaptor, WebApiAdaptor } from '@syncfusion/ej2-data';
// OData V4 — use your own controlled OData endpoint
public dataManager: DataManager = new DataManager({
url: '/api/odata/tasks', // ✅ Use an internal, authenticated endpoint — never a public third-party URL
adaptor: new ODataV4Adaptor()
});
// Web API / REST
public dataManager: DataManager = new DataManager({
url: 'api/tasks',
adaptor: new WebApiAdaptor()
// crossDomain: true — avoid unless required; enforce CORS on the server side instead
});<ejs-gantt [dataSource]="dataManager" [taskFields]="taskFields"></ejs-gantt>Supported adaptors:
ODataAdaptor— OData v3ODataV4Adaptor— OData v4WebApiAdaptor— REST API / ASP.NET Web APIUrlAdaptor— Custom server with Syncfusion data formatJsonAdaptor— Local JSON with DataManager features
---
Load-on-Demand (Virtual Loading)
For large hierarchical datasets, load child tasks only when a parent is expanded. Requires hasChildMapping:
public taskFields: object = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
hasChildMapping: 'isParent', // Boolean field: true if task has children
parentID: 'ParentID'
};<ejs-gantt
[dataSource]="dataManager"
[taskFields]="taskFields"
[loadChildOnDemand]="true">
</ejs-gantt>Important: Without hasChildMapping, load-on-demand triggers actionFailure. Use parentID (not child) for self-referential remote data.
---
Observable Data Binding
Bind to a RxJS Observable when data updates dynamically:
import { Observable, of } from 'rxjs';
public data$: Observable<object[]> = of([
{ TaskID: 1, TaskName: 'Task 1', StartDate: new Date('04/02/2024'), Duration: 4 }
]);<ejs-gantt [dataSource]="data$ | async" [taskFields]="taskFields"></ejs-gantt>Use this pattern when integrating with NgRx store or other reactive state management.
---
Handling CRUD with Remote Data
For remote CRUD operations, configure dataSource with a DataManager that has a crudUrl or individual action URLs:
public dataManager: DataManager = new DataManager({
url: 'api/tasks',
crudUrl: 'api/tasks/crud',
adaptor: new UrlAdaptor()
});Or use separate URLs per action:
public dataManager: DataManager = new DataManager({
url: 'api/tasks',
insertUrl: 'api/tasks/insert',
updateUrl: 'api/tasks/update',
removeUrl: 'api/tasks/delete',
adaptor: new UrlAdaptor()
});Inject EditService and enable editSettings to activate CRUD. The Gantt sends batch requests or individual requests based on the adaptor.
For batch save, use batchUrl:
public dataManager: DataManager = new DataManager({
url: 'api/tasks',
batchUrl: 'api/tasks/batchsave',
adaptor: new UrlAdaptor()
});---
Common Gotchas
| Issue | Cause | Fix |
|---|---|---|
| Tasks not rendering | Missing taskFields.id or taskFields.name | Ensure both are mapped |
| Hierarchy not showing | Wrong field name in child or parentID | Double-check field names match data |
| Remote data not loading | Wrong adaptor type | Match adaptor to your backend protocol |
| CRUD fails | Missing isPrimaryKey column | Set columns.isPrimaryKey: true on the ID column |
| Load-on-demand error | Missing hasChildMapping | Add hasChildMapping to taskFields |
| Parent dates wrong | Using manual mode | Parent dates auto-computed only in taskMode: 'Auto' |
Events in Syncfusion Angular Gantt Chart
Table of Contents
- Overview
- actionBegin
- actionComplete
- actionFailure
- Taskbar editing events
- Row and cell selection events
- Lifecycle events
- Query events
- Other notable events
- Event imports reference
---
Overview
The Syncfusion Angular Gantt Chart component provides a comprehensive event-driven architecture. Events allow you to intercept and customize virtually every action — adding, editing, deleting, sorting, filtering, dependency editing, zooming, and more.
---
actionBegin
Fires before an action is processed. The event argument type varies based on requestType.
Common requestType values
requestType | Triggered by | Arg type |
|---|---|---|
beforeSave | Save after cell/dialog edit | ITaskAddedEventArgs |
beforeAdd | Before add dialog opens | ITaskAddedEventArgs |
beforeDelete | Before task delete | ITaskAddedEventArgs |
taskbarEditing | Taskbar drag start | ITimeSpanEventArgs |
validateDependency | New dependency being drawn | IDependencyEventArgs |
updateDependency | Dependency being updated | IDependencyEventArgs |
filtering | Filter applied | FilterEventArgs |
sorting | Column sorted | SortEventArgs |
zooming | Zoom In/Out/Fit | ZoomEventArgs |
Cancel an action
Set args.cancel = true to prevent the action from proceeding:
public actionBegin(args: ITaskAddedEventArgs | ITimeSpanEventArgs): void {
if (args.requestType === 'beforeDelete') {
// Prevent deletion of tasks with no progress
const data = (args as ITaskAddedEventArgs).data as any;
if (data?.Progress === 0) {
args.cancel = true;
}
}
}ITaskAddedEventArgs properties
| Property | Type | Description |
|---|---|---|
action | string | Action type: beforeAdd, beforeDelete |
cancel | boolean | Set true to cancel |
data | object | Original task data |
modifiedRecords | object[] | Records changed in batch |
modifiedTaskData | object[] | Task data after modification |
newTaskData | object | Data of newly added task |
recordIndex | number | Index of targeted record |
requestType | string | Describes the request type |
rowPosition | string | Top \ |
ITimeSpanEventArgs properties (taskbar editing)
| Property | Type | Description |
|---|---|---|
cancel | boolean | Set true to cancel |
isTimelineRoundOff | boolean | Whether timeline rounding applies |
projectStartDate | Date | Project start boundary |
projectEndDate | Date | Project end boundary |
requestType | string | taskbarEditing |
IDependencyEventArgs properties
| Property | Type | Description |
|---|---|---|
fromItem | object | Source task in the dependency |
toItem | object | Target task in the dependency |
isValidLink | boolean | Whether the link is valid |
newPredecessorString | string | Updated predecessor string |
predecessor | string | Original predecessor string |
requestType | string | validateDependency \ |
FilterEventArgs properties
| Property | Type | Description |
|---|---|---|
cancel | boolean | Set true to cancel |
columns | object[] | Columns being filtered |
currentFilterObject | object | Active filter condition |
currentFilteringColumn | string | Column being filtered |
requestType | string | filtering |
SortEventArgs properties
| Property | Type | Description |
|---|---|---|
cancel | boolean | Set true to cancel |
columnName | string | Column being sorted |
direction | string | Ascending \ |
requestType | string | sorting |
ZoomEventArgs properties
| Property | Type | Description |
|---|---|---|
cancel | boolean | Set true to cancel |
requestType | string | zooming |
timeline | object | Timeline settings after zoom |
---
actionComplete
Fires after an action completes successfully. Mirrors actionBegin argument types but cancel has no effect.
public actionComplete(args: ITaskAddedEventArgs): void {
if (args.requestType === 'save') {
console.log('Task saved:', args.data);
}
if (args.requestType === 'delete') {
console.log('Task deleted');
}
}Common requestType values for actionComplete
requestType | Meaning |
|---|---|
save | Task edit/add saved |
delete | Task deleted |
taskbaredited | Taskbar drag complete |
filterafteropen | Filter menu opened |
filtering | Filter applied |
sorting | Sort applied |
add | Task added |
---
actionFailure
Fires when an action fails (e.g., remote data save error).
public actionFailure(args: any): void {
console.error('Action failed:', args.error);
}---
Taskbar editing events
taskbarEditing
Fires continuously during taskbar drag (resize or move). Use to show live feedback.
import { ITaskbarEditedEventArgs } from '@syncfusion/ej2-angular-gantt';
public taskbarEditing(args: ITaskbarEditedEventArgs): void {
console.log('Dragging task:', args.data.ganttProperties.taskName);
console.log('New start:', args.data.ganttProperties.startDate);
}taskbarEdited
Fires after taskbar drag completes. The data contains updated task fields.
public taskbarEdited(args: ITaskbarEditedEventArgs): void {
if (args.data) {
const task = args.data.taskData as any;
console.log('Task moved — new start:', task.StartDate);
}
}---
Row and cell selection events
rowSelected / rowDeselected
import { RowSelectEventArgs } from '@syncfusion/ej2-angular-gantt';
public rowSelected(args: RowSelectEventArgs): void {
const data = args.data as any;
console.log('Selected task ID:', data.TaskID);
}
public rowDeselected(args: any): void {
console.log('Row deselected');
}cellSelected / cellDeselected
import { CellSelectEventArgs } from '@syncfusion/ej2-angular-gantt';
public cellSelected(args: CellSelectEventArgs): void {
console.log('Cell selected — column:', args.cellIndex?.cellIndex);
}---
Lifecycle events
| Event | When fired |
|---|---|
load | Before the component renders (data not yet bound) |
created | After the component is fully initialized and rendered |
dataBound | After data is bound and the grid is rendered (fires on refresh too) |
destroyed | After component is destroyed |
@Component({
template: `<ejs-gantt
(load)="onLoad()"
(created)="onCreated()"
(dataBound)="onDataBound()">
</ejs-gantt>`
})
export class AppComponent {
public onLoad(): void {
console.log('Gantt loading...');
}
public onCreated(): void {
console.log('Gantt created and ready');
}
public onDataBound(): void {
console.log('Data bound complete');
}
}---
Query events
These events fire during rendering and allow per-row / per-cell / per-taskbar customization.
queryTaskbarInfo
Fires for each taskbar during rendering. Use to apply conditional styles.
import { IQueryTaskbarInfoEventArgs } from '@syncfusion/ej2-angular-gantt';
public queryTaskbarInfo(args: IQueryTaskbarInfoEventArgs): void {
const data = args.data.taskData as any;
if (data.Progress < 30) {
args.taskbarBgColor = '#ff6b6b';
args.progressBarBgColor = '#c0392b';
}
}queryCellInfo
Fires for each grid cell. Use to apply CSS or alter cell content.
import { QueryCellInfoEventArgs } from '@syncfusion/ej2-angular-gantt';
public queryCellInfo(args: QueryCellInfoEventArgs): void {
if (args.column?.field === 'Progress' && (args.data as any).Progress > 80) {
(args.cell as HTMLElement).style.color = 'green';
}
}rowDataBound / row spanning
rowDataBound fires for each row. Use queryCellInfo with rowSpan when you need to merge cells vertically.
public rowDataBound(args: any): void {
const data = args.data.taskData as any;
if (data.Priority === 'High') {
args.row.classList.add('high-priority-row');
}
}---
Other notable events
| Event | Description |
|---|---|
toolbarClick | Fires when any toolbar item is clicked |
contextMenuClick | Fires when a context menu item is clicked |
columnMenuClick | Fires when a column menu item is clicked |
columnDragStart | Fires when column drag begins |
columnDrop | Fires when a column is dropped after reorder |
resizeStart | Fires when column resize begins |
resizeStop | Fires when column resize ends |
rowDragStartHelper | Fires before row drag; can cancel |
rowDragStart | Fires when row drag begins |
rowDrop | Fires when row is dropped |
beforeTooltipRender | Fires before tooltip renders; customize tooltip content |
pdfExportComplete | Fires after PDF export completes (with blob if requested) |
excelExportComplete | Fires after Excel export completes |
onTaskbarClick | Fires when a taskbar is clicked |
recordDoubleClick | Fires on row double-click |
expandCollapsing | Fires before expand/collapse of a parent task |
expanded / collapsed | Fires after expand/collapse |
---
Event imports reference
import {
GanttModule,
GanttComponent,
ITaskAddedEventArgs,
ITimeSpanEventArgs,
IDependencyEventArgs,
IQueryTaskbarInfoEventArgs,
ITaskbarEditedEventArgs,
ZoomEventArgs,
RowSelectEventArgs,
CellSelectEventArgs
} from '@syncfusion/ej2-angular-gantt';
import {
FilterEventArgs,
SortEventArgs,
QueryCellInfoEventArgs
} from '@syncfusion/ej2-angular-grids';Component template binding
<ejs-gantt
(actionBegin)="actionBegin($event)"
(actionComplete)="actionComplete($event)"
(actionFailure)="actionFailure($event)"
(taskbarEditing)="taskbarEditing($event)"
(taskbarEdited)="taskbarEdited($event)"
(rowSelected)="rowSelected($event)"
(cellSelected)="cellSelected($event)"
(queryTaskbarInfo)="queryTaskbarInfo($event)"
(queryCellInfo)="queryCellInfo($event)"
(rowDataBound)="rowDataBound($event)"
(dataBound)="onDataBound()"
(toolbarClick)="toolbarClick($event)">
</ejs-gantt>Excel and PDF Export in Syncfusion Angular Gantt Chart
Table of Contents
- Excel export setup
- Triggering Excel export
- Excel export options
- CSV export
- PDF export setup
- Triggering PDF export
- PDF export options
- PDF header and footer
- Single-page PDF export
- Export blob object
- Multiple Gantt export to one PDF
- Export events
---
Excel export setup
Set allowExcelExport to true and inject ExcelExportService:
import { GanttModule, ExcelExportService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [ExcelExportService],
standalone: true,
template: `
<ejs-gantt #gantt
[dataSource]="data"
[taskFields]="taskSettings"
[allowExcelExport]="true"
[toolbar]="['ExcelExport', 'CsvExport']"
(toolbarClick)="toolbarClick($event)">
</ejs-gantt>
`
})
export class AppComponent {
@ViewChild('gantt') public ganttObj?: GanttComponent;
public toolbarClick(args: ClickEventArgs): void {
if (args.item.id === 'gantt_excelexport') {
this.ganttObj?.excelExport();
}
if (args.item.id === 'gantt_csvexport') {
this.ganttObj?.csvExport();
}
}
}---
Triggering Excel export
| Method | Description |
|---|---|
excelExport() | Export to .xlsx format |
excelExport(properties) | Export with ExcelExportProperties options |
csvExport() | Export to .csv format |
csvExport(properties) | Export with ExcelExportProperties options |
---
Excel export options
Pass an ExcelExportProperties object to customize the export:
import { ExcelExportProperties } from '@syncfusion/ej2-angular-grids';
public toolbarClick(args: ClickEventArgs): void {
if (args.item.id === 'gantt_excelexport') {
const exportProperties: ExcelExportProperties = {
fileName: 'ProjectPlan.xlsx',
// Export only selected records
dataSource: this.ganttObj?.getSelectedRecords() as object[],
// Include hidden columns
includeHiddenColumn: true
};
this.ganttObj?.excelExport(exportProperties);
}
}ExcelExportProperties key options
| Property | Type | Description |
|---|---|---|
fileName | string | Export file name (e.g., 'ProjectPlan.xlsx') |
dataSource | object[] | Custom data source for export (overrides grid data) |
includeHiddenColumn | boolean | Whether to include hidden columns |
columns | ExcelColumn[] | Override column definitions for export |
header | ExcelHeader | Custom header rows above the data |
footer | ExcelFooter | Custom footer rows below the data |
Show/hide columns during export
public toolbarClick(args: ClickEventArgs): void {
if (args.item.id === 'gantt_excelexport') {
// Show StartDate column, hide Duration for this export
this.ganttObj?.showColumn(['StartDate']);
this.ganttObj?.hideColumn(['Duration']);
this.ganttObj?.excelExport();
}
}
public excelExportComplete(): void {
// Restore original visibility
this.ganttObj?.showColumn(['Duration']);
}---
CSV export
CSV export works identically to Excel export but outputs a .csv file:
this.ganttObj?.csvExport();
// Or with custom data:
this.ganttObj?.csvExport({ dataSource: customData, fileName: 'tasks.csv' });---
PDF export setup
Set allowPdfExport to true and inject PdfExportService:
import { GanttModule, PdfExportService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [PdfExportService],
standalone: true,
template: `
<ejs-gantt #gantt
[allowPdfExport]="true"
[toolbar]="['PdfExport']"
(toolbarClick)="toolbarClick($event)">
</ejs-gantt>
`
})
export class AppComponent {
@ViewChild('gantt') public ganttObj?: GanttComponent;
public toolbarClick(args: ClickEventArgs): void {
if (args.item.id === 'gantt_pdfexport') {
this.ganttObj?.pdfExport();
}
}
}Note: PDF export supports only auto-scheduled tasks. Manual scheduling is not currently supported.
---
Triggering PDF export
| Method | Description |
|---|---|
pdfExport() | Export with default settings |
pdfExport(properties) | Export with PdfExportProperties |
pdfExport(properties, isBlob) | When isBlob=true, returns a Blob in pdfExportComplete |
---
PDF export options
import { PdfExportProperties } from '@syncfusion/ej2-angular-gantt';
public toolbarClick(args: ClickEventArgs): void {
if (args.item.id === 'gantt_pdfexport') {
const pdfProperties: PdfExportProperties = {
fileName: 'GanttReport.pdf',
pageOrientation: 'Landscape', // 'Portrait' | 'Landscape'
pageSize: 'A3' // 'A0'–'A9', 'Letter', 'Legal', 'Note'
};
this.ganttObj?.pdfExport(pdfProperties);
}
}PdfExportProperties key options
| Property | Type | Description |
|---|---|---|
fileName | string | PDF file name |
pageOrientation | string | 'Portrait' \ |
pageSize | string | 'A0'–'A9', 'Letter', 'Legal', 'Note' |
fitToWidthSettings | FitToWidthSettings | Single-page export settings |
header | PdfHeader | Header content configuration |
footer | PdfFooter | Footer content configuration |
enableFooter | boolean | Set false to disable footer |
theme | string | Export theme: 'Tailwind3', 'Bootstrap', etc. |
ganttStyle | object | Custom taskbar colors, connector styles |
---
PDF header and footer
import { PdfExportProperties } from '@syncfusion/ej2-angular-gantt';
const pdfProperties: PdfExportProperties = {
header: {
fromTop: 0,
height: 130,
contents: [
{
type: 'Text',
value: 'PROJECT SCHEDULE',
position: { x: 380, y: 0 },
style: { textBrushColor: '#C25050', fontSize: 25 }
},
{
type: 'Line',
points: { x1: 0, y1: 4, x2: 685, y2: 4 },
style: { penColor: '#000000', penSize: 2 }
}
]
},
footer: {
fromBottom: 160,
height: 100,
contents: [
{
type: 'Text',
value: 'Confidential — Page {$current} of {$total}',
position: { x: 250, y: 0 },
style: { textBrushColor: '#888888', fontSize: 10 }
}
]
}
};Header/footer content types
type | Required props | Description |
|---|---|---|
Text | value, position, style | Plain text content |
Line | points, style | Horizontal or diagonal line |
PageNumber | pageNumberType, position, style | Auto page number |
Image | src (base64), position, size | Embedded image |
---
Single-page PDF export
Export all rows to a single PDF page using fitToWidthSettings:
import { PdfExportProperties } from '@syncfusion/ej2-angular-gantt';
const pdfProperties: PdfExportProperties = {
fitToWidthSettings: {
isFitToWidth: true,
chartWidth: '60%', // Chart pane width percentage
gridWidth: '40%' // Grid pane width percentage
}
};
this.ganttObj?.pdfExport(pdfProperties);---
Export blob object
Get a Blob for preview or further processing by passing true as the second argument:
public toolbarClick(args: ClickEventArgs): void {
if (args.item.id === 'gantt_pdfexport') {
this.ganttObj?.pdfExport({}, true); // isBlob = true
}
}
public pdfExportComplete(args: any): void {
if (args.blobData) {
// Open in a new window for preview
const url = URL.createObjectURL(args.blobData);
window.open(url);
}
}---
Multiple Gantt export to one PDF
Export multiple Gantt instances into a single PDF file. Each Gantt occupies a new page:
@Component({
template: `
<button (click)="exportAll()">Export All</button>
<ejs-gantt #gantt1 [allowPdfExport]="true" [dataSource]="data1" [taskFields]="taskSettings"></ejs-gantt>
<ejs-gantt #gantt2 [allowPdfExport]="true" [dataSource]="data2" [taskFields]="taskSettings"></ejs-gantt>
`
})
export class AppComponent {
@ViewChild('gantt1') public gantt1?: GanttComponent;
@ViewChild('gantt2') public gantt2?: GanttComponent;
public exportAll(): void {
const firstExportProps: PdfExportProperties = { multipleExport: { type: 'AppendToPage', blankRows: 2 } };
const secondExportProps: PdfExportProperties = {};
this.gantt1?.pdfExport(firstExportProps, true).then((pdfDoc: any) => {
this.gantt2?.pdfExport(secondExportProps, false, pdfDoc);
});
}
}---
Export events
| Event | Trigger | Use case |
|---|---|---|
beforeExcelExport | Before Excel export starts | Modify data or cancel |
excelExportComplete | After Excel export | Restore column visibility |
beforePdfExport | Before PDF export starts | Modify properties |
pdfExportComplete | After PDF export | Handle blob, cleanup |
pdfQueryTaskbarInfo | Per-taskbar during PDF render | Apply custom colors in PDF |
@Component({
template: `
<ejs-gantt
(beforePdfExport)="beforePdfExport($event)"
(pdfExportComplete)="pdfExportComplete($event)"
(pdfQueryTaskbarInfo)="pdfQueryTaskbarInfo($event)">
</ejs-gantt>
`
})
export class AppComponent {
public beforePdfExport(args: any): void {
console.log('About to export PDF');
}
public pdfExportComplete(args: any): void {
console.log('PDF export done');
}
public pdfQueryTaskbarInfo(args: any): void {
// Customize taskbar colors in the exported PDF
if ((args.data.taskData as any).Priority === 'High') {
args.taskbarBgColor = new PdfColor(231, 76, 60);
}
}
}Filtering and Searching in Angular Gantt Chart
Table of Contents
- Enable Filtering
- Initial Filter on Load
- Filter Operators
- Hierarchy Filtering Modes
- Excel-Like Filter
- Filter Menu Customization
- Searching via Toolbar
- Programmatic Filter and Clear
---
Enable Filtering
Set allowFiltering: true and inject FilterService:
@Component({
providers: [FilterService],
template: `<ejs-gantt [allowFiltering]="true"></ejs-gantt>`
})Filtering icons appear in column headers. Clicking opens a filter dropdown for each column. To disable filtering for a specific column:
{ field: 'TaskID', allowFiltering: false }---
Initial Filter on Load
Pre-apply filters when the Gantt loads using filterSettings.columns:
public filterSettings: object = {
columns: [
{
field: 'TaskName',
operator: 'startswith',
value: 'Design',
predicate: 'and' // 'and' | 'or'
},
{
field: 'Progress',
operator: 'greaterthan',
value: 50,
predicate: 'and'
}
]
};<ejs-gantt [filterSettings]="filterSettings"></ejs-gantt>---
Filter Operators
| Operator | Applies To |
|---|---|
startswith | String |
endswith | String |
contains | String |
equal | String, Number, Boolean, Date |
notequal | String, Number, Boolean, Date |
greaterthan | Number, Date |
greaterthanorequal | Number, Date |
lessthan | Number, Date |
lessthanorequal | Number, Date |
Default operator is equal.
---
Hierarchy Filtering Modes
Control how parent/child tasks are shown when filtering:
public filterSettings: object = {
hierarchyMode: 'Parent' // 'Parent' | 'Child' | 'Both' | 'None'
};| Mode | Behavior |
|---|---|
'Parent' | Shows matching rows AND their parent ancestors |
'Child' | Shows matching rows AND all their children |
'Both' | Shows matching rows, their parents, and their children |
'None' | Shows only exact matching rows (no hierarchy context) |
---
Excel-Like Filter
Enable Excel-style filter UI with checkboxes for each unique value:
public filterSettings: object = {
type: 'Excel' // 'Menu' (default) | 'Excel'
};<ejs-gantt [filterSettings]="filterSettings"></ejs-gantt>Excel filter shows a checklist of unique values per column plus a search box for quick filtering, similar to Microsoft Excel's auto-filter.
---
Filter Menu Customization
Configure what appears in the filter dropdown per column type:
public filterSettings: object = {
type: 'Menu',
operators: {
stringOperator: [
{ value: 'startswith', text: 'Starts With' },
{ value: 'contains', text: 'Contains' }
],
numberOperator: [
{ value: 'equal', text: 'Equal' },
{ value: 'greaterthan', text: 'Greater Than' }
]
}
};---
Searching via Toolbar
Add 'Search' to the toolbar to show a search input:
public toolbar: string[] = ['Search'];
public searchSettings: object = {
fields: ['TaskName', 'TaskID'], // Columns to search in (default: all)
operator: 'contains', // Search operator
key: '', // Initial search value
ignoreCase: true // Case-insensitive search
};<ejs-gantt [toolbar]="toolbar" [searchSettings]="searchSettings"></ejs-gantt>Search filters across all visible rows including children of collapsed parents.
---
Programmatic Filter and Clear
// Filter by field
this.ganttObj.filterByColumn('TaskName', 'startswith', 'Design');
// Filter multiple columns
this.ganttObj.filterByColumn('Progress', 'greaterthan', 50);
// Clear all filters
this.ganttObj.clearFiltering();
// Clear filter for one column
this.ganttObj.clearFiltering(['TaskName']);
// Trigger search programmatically
this.ganttObj.search('Design');Access the Gantt instance via @ViewChild('gantt') ganttObj: GanttComponent.
Gantt Chart - Programmatic Methods Reference
Methods not covered in any other reference file. Use as a supplement for programmatic control.
Table of Contents
- autoFitColumns
- cancelEdit
- changeTaskMode
- clearRedoCollection
- clearUndoCollection
- collapseByIndex
- convertToMilestone
- deleteRecord
- enableItems
- expandByIndex
- getCurrentViewData
- getDurationString
- getExpandedRecords
- getGanttColumns
- getGridColumns
- getRecordByID
- getRedoActions
- getRowByID
- getRowByIndex
- getTaskByUniqueID
- getTaskInfo
- getTaskbarHeight
- getUndoActions
- getWorkString
- openAddDialog
- openEditDialog
- removeSortColumn
- reorderRows
- scrollToTask
- selectCells
- updateChartScrollOffset
- updateDataSource
- updateProjectDates
- updateRecordByID
- updateRecordByIndex
- updateTaskId
---
Angular pattern - access the component instance via @ViewChild:
import { ViewChild } from '@angular/core';
import { GanttComponent } from '@syncfusion/ej2-angular-gantt';
@ViewChild('gantt') public gantt!: GanttComponent;Template: <ejs-gantt #gantt ...></ejs-gantt>
---
autoFitColumns
Adjusts column width(s) to fit content. Call inside dataBound for initial render.
this.gantt.autoFitColumns('TaskName');
this.gantt.autoFitColumns(['TaskName', 'StartDate', 'Duration']);
this.gantt.autoFitColumns(); // all columns| Parameter | Type | Description |
|---|---|---|
fieldNames (optional) | `string | string[]` |
---
cancelEdit
Cancels the active edit operation and reverts unsaved changes. this.gantt.cancelEdit();
---
changeTaskMode
Changes the scheduling mode of a task at runtime (Auto, Manual, or Custom).
const record = this.gantt.getRecordByID('3');
if (record) {
record.taskData.taskMode = 1; // 0=Auto, 1=Manual, 2=Custom
this.gantt.changeTaskMode(record.taskData);
}| Parameter | Type | Description |
|---|---|---|
data | Object | Task data object with updated taskMode. |
---
clearRedoCollection
Clears the redo history stack. this.gantt.clearRedoCollection();
RequiresenableUndoRedo: trueandUndoRedoServiceinjected inproviders.
---
clearUndoCollection
Clears the undo history stack. this.gantt.clearUndoCollection();
RequiresenableUndoRedo: trueandUndoRedoServiceinjected inproviders.
---
collapseByIndex
Collapses a parent row at the given zero-based index. this.gantt.collapseByIndex(2);
Parameter: index - number
---
convertToMilestone
Converts a task into a milestone (sets duration to zero). this.gantt.convertToMilestone('5');
Parameter: id - string
---
deleteRecord
Deletes one or more task records by ID, index, or IGanttData reference.
this.gantt.deleteRecord(3); // single ID
this.gantt.deleteRecord([2, 3, 5]); // multiple IDs
this.gantt.deleteRecord(record); // IGanttData refParameter: taskDetail - number | string | number[] | string[] | IGanttData | IGanttData[]
---
enableItems
Enables or disables toolbar items by their item ID strings.
this.gantt.enableItems(['GanttToolbar_add', 'GanttToolbar_delete'], false);Parameters: items: string[] - toolbar item IDs. isEnable: boolean - true to enable, false to disable.
---
expandByIndex
Expands one or more parent rows by zero-based index.
this.gantt.expandByIndex(1);
this.gantt.expandByIndex([0, 2, 4]);Parameter: index - number | number[]
---
getCurrentViewData
Returns visible task records after all active filters, sorts, and CRUD operations. Returns: Object[]
const visibleRecords: Object[] = this.gantt.getCurrentViewData();---
getDurationString
Formats a duration value with its unit into a readable string (e.g. "3 days").
this.gantt.getDurationString(3, 'day'); // "3 days"
this.gantt.getDurationString(8, 'hour'); // "8 hours"| Parameter | Type | Description |
|---|---|---|
duration | number | Numeric duration value. |
durationUnit | string | 'day', 'hour', or 'minute'. |
Returns: string
---
getExpandedRecords
Returns only expanded records from a given collection. Returns: IGanttData[]
const expanded = this.gantt.getExpandedRecords(this.gantt.flatData);Parameter: records - IGanttData[]
---
getGanttColumns
Returns the current Gantt column model definitions. Returns: ColumnModel[]
const columns = this.gantt.getGanttColumns();---
getGridColumns
Returns raw TreeGrid Column objects - useful for runtime updates to visible, width, or format. Returns: Column[]
const gridCols = this.gantt.getGridColumns();---
getRecordByID
Retrieves the IGanttData object for a task by its ID string. Returns: IGanttData
const record = this.gantt.getRecordByID('3');Parameter: id - string
---
getRedoActions
Returns the current redo stack. Each item has action (e.g. 'add', 'delete', 'sorting') and modifiedRecords.
const redoStack = this.gantt.getRedoActions();
redoStack.forEach(item => console.log(item.action));Returns: Object[]
RequiresenableUndoRedo: trueandUndoRedoServiceinproviders.
---
getRowByID
Returns the DOM HTMLElement for the chart row matching the given task ID. Returns: HTMLElement
const rowEl = this.gantt.getRowByID('5');Parameter: id - string | number
---
getRowByIndex
Returns the DOM HTMLElement for the chart row at the given zero-based index. Returns: HTMLElement
const rowEl = this.gantt.getRowByIndex(0);Parameter: index - number
---
getTaskByUniqueID
Retrieves an IGanttData record using its internal unique ID (not the user-defined task ID). Returns: IGanttData
const record = this.gantt.getTaskByUniqueID('some-unique-id');Parameter: id - string
---
getTaskInfo
Retrieves internal rendering properties (taskbar width, left offset, segments) for a task by ID. Returns: IGanttTaskInfo
const info = this.gantt.getTaskInfo('3');
console.log(info?.width, info?.left, info?.segments);Parameter: taskId - string
---
getTaskbarHeight
Returns the configured taskbar row height in pixels. Returns: number
const height: number = this.gantt.getTaskbarHeight();---
getUndoActions
Returns the current undo stack. Each item has action and modifiedRecords.
const undoStack = this.gantt.getUndoActions();
undoStack.forEach(item => console.log(item.action));Returns: Object[]
RequiresenableUndoRedo: trueandUndoRedoServiceinproviders.
---
getWorkString
Formats a work value with its unit into a readable string (e.g. "24 hours").
this.gantt.getWorkString(24, 'hour'); // "24 hours"| Parameter | Type | Description |
|---|---|---|
work | number | Numeric work value. |
workUnit | string | 'day', 'hour', or 'minute'. |
Returns: string
---
openAddDialog
Opens the add task dialog programmatically. this.gantt.openAddDialog();
RequireseditSettings.allowAdding: trueandEditServiceinproviders.
---
openEditDialog
Opens the edit dialog for a specific task ID, or for the currently selected row if omitted.
this.gantt.openEditDialog(3);
this.gantt.openEditDialog(); // selected row| Parameter | Type | Description |
|---|---|---|
taskId (optional) | `number | string` |
RequireseditSettings.allowEditing: trueandEditServiceinproviders.
---
removeSortColumn
Removes the sort on a specific column without affecting other sorted columns.
this.gantt.removeSortColumn('StartDate');Parameter: columnName - string
---
reorderRows
Moves rows from source indexes to a target drop position.
this.gantt.reorderRows([2, 3], 0, 'above');
this.gantt.reorderRows([4], 1, 'child');| Parameter | Type | Description |
|---|---|---|
fromIndexes | number[] | Zero-based indexes of rows to move. |
toIndex | number | Zero-based index of the target row. |
position | string | 'above', 'below', or 'child'. |
RequiresallowRowDragAndDrop: trueandRowDDServiceinproviders.
---
scrollToTask
Scrolls the chart timeline to bring the taskbar of the specified task into view.
this.gantt.scrollToTask('5');Parameter: taskId - string
---
selectCells
Selects multiple cells by row and column index pairs.
this.gantt.selectCells([
{ rowIndex: 0, cellIndexes: [1, 2] },
{ rowIndex: 2, cellIndexes: [0] },
]);Parameter: rowCellIndexes - ISelectedCell[] (from @syncfusion/ej2-grids)
RequiresselectionSettings.mode: 'Cell'andSelectionServiceinproviders.
---
updateChartScrollOffset
Sets both horizontal and vertical scroll positions of the chart pane simultaneously.
this.gantt.updateChartScrollOffset(500, 200); // left=500px, top=200pxParameters: left: number - horizontal px offset. top: number - vertical px offset.
---
updateDataSource
Replaces the entire data source at runtime with optional project date bounds.
this.gantt.updateDataSource(newData, {
projectStartDate: new Date('2024-01-01'),
projectEndDate: new Date('2024-12-31'),
});| Parameter | Type | Description |
|---|---|---|
dataSource | Object[] | New task data collection. |
args | object | Optional projectStartDate and projectEndDate Date values. |
---
updateProjectDates
Updates the project start/end dates, optionally rounding to timeline unit boundaries.
this.gantt.updateProjectDates(
new Date('2024-01-01'),
new Date('2024-12-31'),
true // round off to nearest timeline unit
);| Parameter | Type | Description |
|---|---|---|
startDate | Date | New project start date. |
endDate | Date | New project end date. |
isTimelineRoundOff | boolean | Round to nearest timeline unit boundary. |
isFrom (optional) | string | Origin context string. |
---
updateRecordByID
Updates an existing task record by primary key ID. Only provided fields are updated.
this.gantt.updateRecordByID({ TaskID: 3, TaskName: 'Updated', Duration: 7 });Parameter: data - Object (task ID + fields to update)
---
updateRecordByIndex
Updates a task record at the specified zero-based row index.
this.gantt.updateRecordByIndex(2, { TaskName: 'Revised', Duration: 4 });Parameters: index: number, data: Object
---
updateTaskId
Changes an existing task ID to a new unique ID. this.gantt.updateTaskId(3, 99);
Parameters: currentId: number | string, newId: number | string
Getting Started with Angular Gantt Chart
Table of Contents
- Prerequisites
- Installation
- CSS Imports
- Add the Component
- Bind Data
- Configure Task Fields
- Inject Feature Modules
- Configure Timeline
- Enable Toolbar
- Enable Editing
- Enable Filtering and Sorting
- Define Event Markers
- Handle Errors
- Run the Application
---
Prerequisites
- Node.js 18.19 or later
- Angular CLI installed globally
- npm or yarn package manager
- Basic knowledge of Angular framework
npm install -g @angular/cli---
Installation
Create a new Angular application:
ng new syncfusion-angular-appInstall the Gantt Chart package using ng add (recommended):
cd syncfusion-angular-app
ng add @syncfusion/ej2-angular-ganttThis command performs the following:
- Installs required dependencies
- Imports the Gantt module
- Registers default theme styles in
angular.json
Or install manually:
npm install @syncfusion/ej2-angular-gantt --save---
CSS Imports
The Gantt component requires specific CSS files for proper rendering. Add to src/styles.css:
@import '../node_modules/@syncfusion/ej2-gantt/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-base/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-grids/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-treegrid/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-layouts/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-popups/styles/tailwind3.css';Note: Additional styles are required when enabling advanced features such as editing, toolbar, or dialogs:
```css
/ For editing, toolbar, and dialog features /
@import '../node_modules/@syncfusion/ej2-calendars/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-dropdowns/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-inputs/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-buttons/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-navigations/styles/tailwind3.css';
@import '../node_modules/@syncfusion/ej2-notifications/styles/tailwind3.css';
>
/ For rich text editor in dialog notes tab /
@import '../node_modules/@syncfusion/ej2-richtexteditor/styles/tailwind3.css';
```
Other available themes: material3, bootstrap5, fluent2.
---
Add the Component
Modify src/app/app.ts (Angular 20+) or src/app/app.component.ts (Angular 19 and below):
import { Component, ViewEncapsulation } from '@angular/core';
import { GanttModule } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
standalone: true,
selector: 'app-root',
template: `<ejs-gantt [dataSource]="data" [taskFields]="taskSettings"></ejs-gantt>`,
encapsulation: ViewEncapsulation.None
})
export class App {
public data = [
{TaskID: 1, TaskName: 'Project initiation', StartDate: new Date('2024-04-01'), EndDate: new Date('2024-04-15')},
{TaskID: 2, TaskName: 'Identify site location', StartDate: new Date('2024-04-01'), Duration: 4, ParentID: 1},
{TaskID: 3, TaskName: 'Perform site survey', StartDate: new Date('2024-04-01'), Duration: 4, ParentID: 1},
{TaskID: 4, TaskName: 'Soil testing', StartDate: new Date('2024-04-01'), Duration: 3, ParentID: 1},
{TaskID: 5, TaskName: 'Project estimation', StartDate: new Date('2024-04-08'), EndDate: new Date('2024-04-18')},
{TaskID: 6, TaskName: 'Develop floor plan', StartDate: new Date('2024-04-08'), Duration: 5, ParentID: 5},
{TaskID: 7, TaskName: 'Estimate project cost', StartDate: new Date('2024-04-08'), Duration: 5, ParentID: 5},
];
public taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
parentID: 'ParentID'
};
}This renders a Gantt chart with task hierarchy. Two data patterns are supported:
- Self-referential (shown above): Flat array with
id+parentID— use this by default - Hierarchical: Nested
subtasksarray — only when user explicitly requests nested/tree structure
---
Configure Task Fields
The taskFields property maps data fields to Gantt properties:
public taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
parentID: 'ParentID'
};Essential `taskFields` mappings:
| Property | Maps to | Required |
|---|---|---|
id | Unique task ID | Yes |
name | Task name | Yes |
startDate | Start date | Yes |
endDate / duration | End date or duration | One required |
progress | Completion % | Optional |
dependency | Predecessor IDs (e.g., '3FS') | Optional |
child | Child tasks array | For hierarchical data |
parentID | Parent task ID | For self-referential data |
`dateFormat`: Use the top-leveldateFormatproperty to set the default display format for all date columns globally (e.g.,dateFormat="MM/dd/yyyy"). Individual columnformatoverrides this per-column.
---
Inject Feature Modules
Inject services in the providers array to enable features:
import { Component } from '@angular/core';
import {
GanttModule,
EditService, FilterService, SortService,
ToolbarService, SelectionService, DayMarkersService
} from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
standalone: true,
providers: [EditService, FilterService, SortService, ToolbarService, SelectionService, DayMarkersService],
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskFields"
[toolbar]="toolbar"
[allowFiltering]="true"
[allowSorting]="true"
[editSettings]="editSettings">
</ejs-gantt>
`
})
export class AppComponent {
public data: object[] = [];
public taskFields: object = {};
public toolbar: string[] = ['Add', 'Edit', 'Delete'];
public editSettings: object = { allowEditing: true, allowAdding: true, allowDeleting: true };
}Omitting a required service disables its feature at runtime.
---
Configure Timeline
Use timelineSettings to define the top/bottom tiers and date formats:
public timelineSettings: object = {
topTier: {
unit: 'Week',
format: 'MMM dd, yyyy'
},
bottomTier: {
unit: 'Day',
count: 1
}
};Set project date range:
<ejs-gantt
[timelineSettings]="timelineSettings"
projectStartDate="04/01/2024"
projectEndDate="06/30/2024">
</ejs-gantt>---
Enable Toolbar
Add ToolbarService to providers and set the toolbar array:
public toolbar: string[] = ['Add', 'Edit', 'Delete', 'ExpandAll', 'CollapseAll', 'Search', 'ZoomIn', 'ZoomOut', 'ZoomToFit'];Without ToolbarService, toolbar won't render.
---
Enable Editing
Set editSettings and inject EditService:
public editSettings: object = {
allowEditing: true, // Enable cell/dialog editing
allowAdding: true, // Enable adding new tasks
allowDeleting: true, // Enable deleting tasks
allowTaskbarEditing: true, // Enable drag/resize taskbars
mode: 'Auto' // 'Auto' = cell editing | 'Dialog' = dialog editing
};- Cell editing:
mode: 'Auto'— double-click a TreeGrid cell - Dialog editing:
mode: 'Dialog'— double-click anywhere opens dialog - Taskbar editing:
allowTaskbarEditing: true— drag/resize taskbars on the chart
---
Enable Filtering and Sorting
<ejs-gantt [allowFiltering]="true" [allowSorting]="true">
</ejs-gantt>Inject FilterService and SortService in providers. Filtering adds filter icons to column headers; sorting enables click-to-sort.
---
Define Event Markers
Event markers highlight important project dates with vertical lines:
// Inject DayMarkersService
public eventMarkers: object[] = [
{ day: new Date('04/10/2024'), label: 'Kickoff meeting', cssClass: 'e-custom-event-marker' },
{ day: new Date('05/15/2024'), label: 'Mid-project review' }
];<ejs-gantt [eventMarkers]="eventMarkers"></ejs-gantt>Missing DayMarkersService prevents marker rendering.
---
Handle Errors
Subscribe to the actionFailure event to catch configuration issues:
public actionFailure(args: any): void {
console.error('Gantt action failed:', args.error);
}<ejs-gantt (actionFailure)="actionFailure($event)"></ejs-gantt>Common causes: missing isPrimaryKey, invalid dependency format, missing hasChildMapping for load-on-demand, invalid timelineSettings.format.
---
Grid Lines
Control which grid lines are rendered in the TreeGrid (left) and chart (right) panes:
<ejs-gantt gridLines="Both"></ejs-gantt>| Value | Description |
|---|---|
'Both' | Horizontal and vertical lines in both panes (default) |
'Horizontal' | Only horizontal row separator lines |
'Vertical' | Only vertical column divider lines |
'None' | No grid lines |
// Programmatic toggle
this.ganttObj.gridLines = 'Horizontal';---
Run the Application
ng serve --openThe browser opens at http://localhost:4200 showing the Gantt chart.
Troubleshooting checklist:
- Styles not showing → Verify CSS import order in
styles.css - Editing not working → Check
EditServiceis inproviders - Toolbar not visible → Check
ToolbarServiceis inproviders - Tasks not rendering → Verify
taskFields.id,taskFields.name,taskFields.startDateare mapped
Holidays and Event Markers in Syncfusion Angular Gantt Chart
Table of Contents
- DayMarkersService requirement
- Holidays
- Holiday effects on task scheduling
- Holiday configuration properties
- Single and multi-day holidays
- Custom holiday styling
- Event Markers
- Event marker properties
- Multiple event markers
- Vertical offset with top
---
DayMarkersService requirement
Both holidays and event markers require DayMarkersService to be injected in the component's providers:
import { GanttModule, DayMarkersService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [DayMarkersService],
standalone: true
})
export class AppComponent { }Without this service, holidays will not render in the timeline, and event markers will not appear.
---
Holidays
The holidays property defines non-working days that affect task duration and scheduling. Holidays take precedence over workWeek and includeWeekend settings.
Holiday effects on task scheduling
| Effect | Description |
|---|---|
| Duration adjustments | Task durations exclude holidays; end dates extend past holiday periods |
| Dependency management | Successor tasks shift automatically to respect FS/SS/FF/SF relationships |
| Critical path | Holidays impact slack calculations (enableCriticalPath) — delayed tasks may become critical |
| Resource allocation | Holidays pause resource availability; task progress halts during these periods |
| Timeline rendering | Holidays appear as highlighted background regions with descriptive labels |
Holiday configuration properties
| Property | Type | Description |
|---|---|---|
from | Date | Start date of the holiday (required) |
to | Date | End date for multi-day holidays (optional for single-day) |
label | string | Display label shown in timeline (e.g., "Christmas Day") |
cssClass | string | CSS class for custom styling of this holiday region |
Single and multi-day holidays
@Component({
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskSettings"
[holidays]="holidays">
</ejs-gantt>
`
})
export class AppComponent {
public holidays = [
// Single-day holiday
{
from: new Date('2024-12-25'),
label: 'Christmas Day',
cssClass: 'national-holiday'
},
// Multi-day holiday
{
from: new Date('2024-12-25'),
to: new Date('2024-12-26'),
label: 'Christmas Break',
cssClass: 'national-holiday'
},
// Company closure
{
from: new Date('2024-12-31'),
to: new Date('2025-01-01'),
label: 'New Year Break',
cssClass: 'company-holiday'
}
];
}Custom holiday styling
Apply custom CSS for different holiday types using the cssClass property:
/* Global or component styles */
.e-gantt .national-holiday {
background-color: rgba(255, 100, 100, 0.2);
border-left: 2px solid #e74c3c;
}
.e-gantt .company-holiday {
background-color: rgba(255, 165, 0, 0.2);
border-left: 2px solid #f39c12;
}---
Event Markers
Event markers display vertical lines across the entire Gantt chart at specific dates. They represent project-wide milestones, deadlines, or critical dates — visible across all rows and during scroll/zoom.
Unlike data markers (indicators tied to individual task rows), event markers span the full chart height.
Event marker properties
| Property | Type | Description |
|---|---|---|
day | Date \ | string |
label | string | Descriptive label displayed at the top of the marker line |
cssClass | string | CSS class for custom styling of the marker line |
top | number | Vertical offset in pixels from the chart content top (for staggering overlapping markers) |
Multiple event markers
@Component({
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskSettings"
[eventMarkers]="eventMarkers">
</ejs-gantt>
`
})
export class AppComponent {
public eventMarkers = [
{
day: new Date('2024-04-15'),
label: 'Phase 1 Review',
cssClass: 'review-marker'
},
{
day: new Date('2024-05-01'),
label: 'Go Live',
cssClass: 'go-live-marker'
},
{
day: new Date('2024-06-01'),
label: 'Project Deadline',
cssClass: 'deadline-marker'
}
];
}Vertical offset with top
When multiple markers share the same date, use top to stagger them vertically:
public eventMarkers = [
{
day: new Date('2024-04-15'),
label: 'Stakeholder Review',
cssClass: 'review-marker',
top: 0 // At chart top
},
{
day: new Date('2024-04-15'),
label: 'Budget Freeze',
cssClass: 'budget-marker',
top: 20 // 20px below first marker
}
];Event marker CSS customization
.e-gantt .review-marker .e-span-label {
color: #2980b9;
font-weight: bold;
}
.e-gantt .review-marker .e-gantt-event-marker {
border-left: 2px dashed #2980b9;
}
.e-gantt .deadline-marker .e-gantt-event-marker {
border-left: 2px solid #e74c3c;
}
.e-gantt .deadline-marker .e-span-label {
color: #e74c3c;
}---
Full example: holidays + event markers
import { Component } from '@angular/core';
import { GanttModule, DayMarkersService } from '@syncfusion/ej2-angular-gantt';
@Component({
imports: [GanttModule],
providers: [DayMarkersService],
standalone: true,
selector: 'app-root',
template: `
<ejs-gantt
[dataSource]="data"
[taskFields]="taskSettings"
[holidays]="holidays"
[eventMarkers]="eventMarkers"
height="450px">
</ejs-gantt>
`
})
export class AppComponent {
public taskSettings = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
child: 'subtasks'
};
public holidays = [
{ from: new Date('2024-04-05'), label: 'Company Off Day', cssClass: 'company-holiday' },
{ from: new Date('2024-04-12'), to: new Date('2024-04-14'), label: 'Easter Break', cssClass: 'national-holiday' }
];
public eventMarkers = [
{ day: new Date('2024-04-08'), label: 'Sprint Review', cssClass: 'review-marker' },
{ day: new Date('2024-04-22'), label: 'Release Deadline' }
];
public data = [
{
TaskID: 1, TaskName: 'Planning Phase',
StartDate: new Date('2024-04-01'), EndDate: new Date('2024-04-20'),
subtasks: [
{ TaskID: 2, TaskName: 'Requirements', StartDate: new Date('2024-04-01'), Duration: 5, Progress: 100 },
{ TaskID: 3, TaskName: 'Design', StartDate: new Date('2024-04-08'), Duration: 5, Progress: 60 }
]
}
];
}````markdown
Localization, RTL and Formatting in Angular Gantt Chart
Table of Contents
- Setting the Locale
- Loading Translations (L10n)
- Gantt Locale Key Reference
- Right-to-Left (RTL)
- Timezone Configuration
- Column Date Formatting
- Column Number Formatting
---
Setting the Locale
Set the locale property to apply a language culture to Gantt UI strings:
<ejs-gantt locale="fr" ...></ejs-gantt>Combine with setCulture from @syncfusion/ej2-base for date/number formatting:
import { setCulture } from '@syncfusion/ej2-base';
setCulture('fr');---
Loading Translations (L10n)
Call L10n.load() before the component is initialized to provide translated strings for all Gantt UI text:
import { L10n, setCulture } from '@syncfusion/ej2-base';
// In main.ts or app.config.ts — before bootstrapping
L10n.load({
'fr': {
'gantt': {
'id': 'Identifiant',
'name': 'Nom de la tâche',
'startDate': 'Date de début',
'endDate': 'Date de fin',
'duration': 'Durée',
'progress': 'Progression',
'dependency': 'Dépendances',
'notes': 'Remarques',
'baselines': 'Bases de référence',
'baselineStartDate': 'Début de référence',
'baselineEndDate': 'Fin de référence',
'resourceName': 'Ressources',
'resourceID': 'ID Ressource',
'workUnit': 'Unité de travail',
'taskType': 'Type de tâche',
'add': 'Ajouter',
'edit': 'Modifier',
'update': 'Mettre à jour',
'delete': 'Supprimer',
'cancel': 'Annuler',
'search': 'Rechercher',
'task': 'Tâche',
'tasks': 'Tâches',
'zoomIn': 'Zoom avant',
'zoomOut': 'Zoom arrière',
'zoomToFit': 'Ajuster',
'expandAll': 'Développer tout',
'collapseAll': 'Réduire tout',
'undo': 'Annuler',
'redo': 'Rétablir',
'excelExport': 'Export Excel',
'pdfExport': 'Export PDF',
'csvExport': 'Export CSV',
'okText': 'OK',
'confirmDelete': 'Voulez-vous supprimer l\'enregistrement ?',
'from': 'De',
'to': 'À',
'taskBeforePredecessor_FS': 'Vous avez déplacé \"{0}\" avant que \"{1}\" se termine...',
'taskAfterPredecessor_FS': '\"{0}\" a été déplacé et n\'est plus dépendant de \"{1}\".',
'invalidLink': 'Lien invalide',
'taskInformation': 'Informations sur la tâche',
'deleteTask': 'Supprimer la tâche',
'deleteDependency': 'Supprimer la dépendance',
'convert': 'Convertir',
'save': 'Enregistrer',
'above': 'Au-dessus',
'below': 'En dessous',
'child': 'Enfant',
'milestone': 'Jalon',
'toTask': 'Vers tâche',
'toMilestone': 'Vers jalon',
'eventMarkers': 'Marqueurs d\'événements',
'leftTaskLabel': 'Étiquette gauche',
'rightTaskLabel': 'Étiquette droite',
'timelineCell': 'Cellule chronologie',
'collapseAllTasks': 'Réduire toutes les tâches',
'expandAllTasks': 'Développer toutes les tâches',
'durationUnit': {
'day': 'Jour',
'hour': 'Heure',
'minute': 'Minute',
'days': 'Jours',
'hours': 'Heures',
'minutes': 'Minutes'
}
}
}
});
setCulture('fr');---
Gantt Locale Key Reference
Key strings available in the 'gantt' namespace for translation:
| Key | Default (en) | Purpose |
|---|---|---|
id | 'ID' | Task ID column header |
name | 'Name' | Task name column header |
startDate | 'Start Date' | Start Date column header |
endDate | 'End Date' | End Date column header |
duration | 'Duration' | Duration column header |
progress | 'Progress' | Progress column header |
dependency | 'Dependency' | Dependency column header |
notes | 'Notes' | Notes tab label |
resourceName | 'Resources' | Resources column header |
add | 'Add' | Add toolbar button |
edit | 'Edit' | Edit toolbar button |
update | 'Update' | Update toolbar button |
delete | 'Delete' | Delete toolbar button |
cancel | 'Cancel' | Cancel toolbar button |
search | 'Search' | Search placeholder |
zoomIn | 'Zoom In' | Zoom In toolbar button |
zoomOut | 'Zoom Out' | Zoom Out toolbar button |
zoomToFit | 'Zoom To Fit' | Zoom To Fit toolbar button |
expandAll | 'Expand All' | Expand All toolbar button |
collapseAll | 'Collapse All' | Collapse All toolbar button |
undo | 'Undo' | Undo toolbar button |
redo | 'Redo' | Redo toolbar button |
excelExport | 'Excel Export' | Excel Export toolbar button |
pdfExport | 'PDF Export' | PDF Export toolbar button |
confirmDelete | 'Are you sure...' | Delete confirmation dialog text |
taskInformation | 'Task Information' | Context menu / dialog title |
deleteTask | 'Delete Task' | Context menu item |
deleteDependency | 'Delete Dependency' | Context menu item |
convert | 'Convert' | Convert context menu item |
save | 'Save' | Save context menu item |
above | 'Above' | Add above context menu item |
below | 'Below' | Add below context menu item |
child | 'Child' | Add child context menu item |
milestone | 'Milestone' | Milestone context menu item |
toTask | 'To Task' | Convert to task context menu item |
toMilestone | 'To Milestone' | Convert to milestone context menu item |
invalidLink | 'Invalid Link' | Dependency validation message |
durationUnit.day | 'day' | Duration unit label |
durationUnit.hour | 'hour' | Duration unit label |
---
Right-to-Left (RTL)
Enable RTL layout for Arabic, Hebrew, and other right-to-left languages:
<ejs-gantt [enableRtl]="true" locale="ar" ...></ejs-gantt>RTL effects:
- Column headers render right-to-left
- TreeGrid expand/collapse icons shift to right side
- Taskbar connector arrows reverse direction
- Dialog and toolbar button layout reverses
- Scrollbar appears on left side
import { L10n, setCulture } from '@syncfusion/ej2-base';
// Load Arabic translations
L10n.load({
'ar': {
'gantt': {
'id': 'المعرف',
'name': 'اسم المهمة',
'startDate': 'تاريخ البدء',
'duration': 'المدة',
'progress': 'التقدم',
'add': 'إضافة',
'edit': 'تعديل',
'delete': 'حذف',
'cancel': 'إلغاء',
'update': 'تحديث'
}
}
});
setCulture('ar');<ejs-gantt [enableRtl]="true" locale="ar"></ejs-gantt>---
Timezone Configuration
By default, the Gantt uses the browser's system timezone. Use timezone to fix all dates to a specific IANA timezone for consistent display across global users:
<ejs-gantt [timezone]="'UTC'" ...></ejs-gantt><ejs-gantt [timezone]="'America/New_York'" ...></ejs-gantt>Common IANA timezone values:
| Timezone | String |
|---|---|
| UTC | 'UTC' |
| US Eastern | 'America/New_York' |
| US Central | 'America/Chicago' |
| US Pacific | 'America/Los_Angeles' |
| London | 'Europe/London' |
| Paris | 'Europe/Paris' |
| Berlin | 'Europe/Berlin' |
| India | 'Asia/Kolkata' |
| Tokyo | 'Asia/Tokyo' |
| Sydney | 'Australia/Sydney' |
Thetimezoneproperty is most useful when the timeline shows hours. SettimelineViewMode: 'Hour'or configurebottomTier.unit: 'Hour'.
---
Column Date Formatting
Control how dates are displayed in columns using the format property:
public columns: object[] = [
{
field: 'StartDate',
headerText: 'Start Date',
format: 'MM/dd/yyyy', // Custom pattern
type: 'date'
},
{
field: 'EndDate',
headerText: 'End Date',
format: { type: 'date', skeleton: 'yMd' } // Locale-aware skeleton
}
];Common date format tokens:
| Token | Example | Meaning |
|---|---|---|
MM/dd/yyyy | 04/15/2024 | US date format |
dd/MM/yyyy | 15/04/2024 | European format |
yyyy-MM-dd | 2024-04-15 | ISO format |
MMM dd, yyyy | Apr 15, 2024 | Long format |
yMd (skeleton) | Locale-aware | Adapts to locale |
---
Column Number Formatting
Format numeric columns using standard format strings:
public columns: object[] = [
{ field: 'Progress', format: 'N0', textAlign: 'Right' }, // Integer
{ field: 'Cost', format: 'C2', textAlign: 'Right' }, // Currency
{ field: 'Rate', format: 'P1', textAlign: 'Right' }, // Percentage
];| Format | Example | Meaning |
|---|---|---|
'N0' | 42 | Number, 0 decimals |
'N2' | 42.50 | Number, 2 decimals |
'C0' | $42 | Currency, 0 decimals |
'C2' | $42.50 | Currency, 2 decimals |
'P0' | 75% | Percentage, 0 decimals |
'P1' | 75.5% | Percentage, 1 decimal |
````
Managing Tasks in Angular Gantt Chart
Table of Contents
- Prerequisites for Editing
- editSettings Configuration
- Adding Tasks
- Editing Tasks — Cell Mode
- Editing Tasks — Dialog Mode
- Taskbar Editing
- Customizing the Edit Dialog
- Deleting Tasks
- Drag and Drop (Row Reordering)
- Indent and Outdent
- Expand and Collapse
- Maintaining Data in Server (CRUD)
- Validation
- Programmatic CRUD Methods
---
Prerequisites for Editing
1. Inject EditService into providers 2. A primary key column must be defined — by default, the taskFields.id column is the primary key 3. If custom columns are defined, set isPrimaryKey: true on one column
Missing isPrimaryKey will trigger actionFailure.
---
editSettings Configuration
public editSettings: object = {
allowEditing: true, // Enable cell/dialog editing
allowAdding: true, // Enable adding new tasks
allowDeleting: true, // Enable deleting tasks
allowTaskbarEditing: true, // Enable taskbar drag/resize
mode: 'Auto', // 'Auto' = cell editing | 'Dialog' = dialog
showDeleteConfirmDialog: true // Show confirmation before delete
};---
Adding Tasks
Via toolbar: Include 'Add' in the toolbar array. Clicking opens a new task dialog (or inserts a row for cell mode).
With default values: Pre-populate the new task dialog using actionBegin with requestType: 'beforeOpenAddDialog':
public actionBegin(args: any): void {
if (args.requestType === 'beforeOpenAddDialog') {
args.rowData.StartDate = new Date('04/10/2024');
args.rowData.Duration = 5;
}
}Programmatic add:
this.ganttObj.addRecord({
TaskID: 10,
TaskName: 'New Task',
StartDate: new Date('04/10/2024'),
Duration: 3
}, 'Below', 2); // Position: 'Top' | 'Bottom' | 'Above' | 'Below' | 'Child'---
Editing Tasks — Cell Mode
Set editSettings.mode: 'Auto' and double-click a cell in the TreeGrid pane to edit inline:
public editSettings: object = { allowEditing: true, mode: 'Auto' };Cell edit types per column:
'numericedit'→ NumericTextBox (for numbers)'defaultedit'→ TextBox (for strings)'dropdownedit'→ DropDownList'booleanedit'→ CheckBox'datepickeredit'→ DatePicker'datetimepickeredit'→ DateTimePicker
Configure via column definition:
public columns: object[] = [
{ field: 'TaskName', editType: 'defaultedit' },
{ field: 'Duration', editType: 'numericedit', edit: { params: { decimals: 0, min: 0 } } }
];In Auto mode, double-clicking the chart pane opens the edit dialog instead.
---
Editing Tasks — Dialog Mode
Set editSettings.mode: 'Dialog' — double-clicking anywhere opens the edit dialog:
public editSettings: object = { allowEditing: true, mode: 'Dialog' };The dialog contains tabs: General, Dependency, Notes, and custom tabs.
---
Taskbar Editing
Drag and resize taskbars directly on the Gantt chart:
public editSettings: object = {
allowTaskbarEditing: true
};Actions:
- Drag taskbar: Moves start and end dates together
- Drag left edge: Adjusts start date
- Drag right edge: Adjusts end/duration
- Drag connector point: Creates/modifies dependency
taskbarEditing event fires during drag; taskbarEdited fires after completion.
---
Customizing the Edit Dialog
Restrict which tabs and fields appear in add/edit dialogs:
public addDialogFields: object[] = [
{ type: 'General', headerText: 'Task Info', fields: ['TaskName', 'StartDate', 'Duration'] },
{ type: 'Dependency' },
{ type: 'Notes' }
];
public editDialogFields: object[] = [
{ type: 'General', fields: ['TaskName', 'StartDate', 'EndDate', 'Progress'] },
{ type: 'Dependency' },
{ type: 'Resources' }
];<ejs-gantt
[addDialogFields]="addDialogFields"
[editDialogFields]="editDialogFields">
</ejs-gantt>Available tab types: 'General', 'Dependency', 'Resources', 'Notes', 'Custom'
---
Deleting Tasks
Include 'Delete' in toolbar or use deleteRecord(). With showDeleteConfirmDialog: true, a confirmation prompt appears before deletion.
this.ganttObj.deleteRecord(3); // Delete task with TaskID 3---
Drag and Drop (Row Reordering)
Reorder rows by dragging them to new positions:
// Inject RowDDService (already included with EditService)
public allowRowDragAndDrop: boolean = true;<ejs-gantt [allowRowDragAndDrop]="true"></ejs-gantt>Handle drop events to apply custom logic:
public rowDrop(args: any): void {
console.log('Dropped task:', args.data, 'Target:', args.dropIndex);
}---
Indent and Outdent
Promote or demote tasks in the hierarchy via toolbar or programmatically:
public toolbar: string[] = ['Indent', 'Outdent'];
// Programmatic
this.ganttObj.indent(); // Make selected task a child of task above
this.ganttObj.outdent(); // Move selected task up one level in hierarchy---
Expand and Collapse
Expand or collapse task rows programmatically or via toolbar:
// Expand / collapse all
this.ganttObj.expandAll();
this.ganttObj.collapseAll();
// Expand / collapse a specific task by its ID
this.ganttObj.expandByID(1); // Expand task with TaskID 1
this.ganttObj.collapseByID(1); // Collapse task with TaskID 1Use the toolbar items 'ExpandAll' and 'CollapseAll' for user-triggered expand/collapse.
Listen to expand/collapse events:
public expanding(args: any): void {
if (args.data.Progress === 0) {
args.cancel = true; // Prevent expanding tasks with no progress
}
}<ejs-gantt
(expanding)="expanding($event)"
(expanded)="expanded($event)"
(collapsing)="collapsing($event)"
(collapsed)="collapsed($event)">
</ejs-gantt>---
Maintaining Data in Server (CRUD)
For server-side persistence, configure the DataManager with CRUD URLs and handle the dataStateChange event or use built-in adaptor batch updates.
Event-driven approach:
public actionComplete(args: any): void {
if (args.requestType === 'save') {
// args.data contains the updated task
this.httpClient.put('/api/tasks/' + args.data.TaskID, args.data).subscribe();
}
if (args.requestType === 'delete') {
this.httpClient.delete('/api/tasks/' + args.data[0].TaskID).subscribe();
}
}Adaptor approach (recommended for REST APIs):
public dataManager: DataManager = new DataManager({
url: 'api/tasks',
insertUrl: 'api/tasks/insert',
updateUrl: 'api/tasks/update',
removeUrl: 'api/tasks/delete',
adaptor: new UrlAdaptor()
});---
Validation
The actionBegin event fires before edits are committed. Cancel to prevent the operation:
public actionBegin(args: any): void {
if (args.requestType === 'beforeSave') {
if (!args.data.TaskName || args.data.TaskName.trim() === '') {
args.cancel = true; // Block save
alert('Task name is required');
}
}
}For dependency validation conflicts, use requestType: 'validateLinkedTask'.
---
Programmatic CRUD Methods
// Add a new record — position: 'Top' | 'Bottom' | 'Above' | 'Below' | 'Child'
this.ganttObj.addRecord(taskData, 'Bottom');
this.ganttObj.addRecord(taskData, 'Child', 1); // Add as child of task with index 1
// Open add/edit dialogs programmatically
this.ganttObj.openAddDialog(); // Opens the add task dialog
this.ganttObj.openEditDialog(3); // Opens edit dialog for task with TaskID 3
// Update by ID
this.ganttObj.updateRecordById({ TaskID: 3, TaskName: 'Updated', Duration: 5 });
// Delete by ID
this.ganttObj.deleteRecord(3);
// Update task ID
this.ganttObj.updateTaskId(oldID, newID);
// Refresh all data
this.ganttObj.refresh();Access the component instance with @ViewChild('gantt') ganttObj: GanttComponent.