- Configuration and implementation
- Managing WBS code updates
- Limitations
Contact Support
Work Breakdown Structure (WBS) in React Gantt Component
30 Jun 202524 minutes to read
The Work Breakdown Structure (WBS) organizes project tasks hierarchically in the Gantt component by assigning unique codes to each task. This system enhances visualization and management by clearly reflecting task relationships and levels. It is especially useful in complex environments like construction projects or enterprise-scale software development.
Configuration and implementation
To enable and configure WBS in your Gantt component:
-
Enable WBS Codes: Set the
enableWBS
property totrue
to automatically generate unique task codes and their predecessors. -
Auto-Update Codes: Set the
enableAutoWbsUpdate
property totrue
to maintain WBS code accuracy during operations like sorting, filtering, editing, or drag-and-drop.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Selection, ColumnsDirective, ColumnDirective, Toolbar, DayMarkers, Edit, Filter, Sort, ContextMenu, EventMarkersDirective, EventMarkerDirective } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
import { useRef } from 'react';
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
endDate: "EndDate",
duration: "Duration",
progress: "Progress",
dependency: "Predecessor",
parentID: 'ParentId'
};
let ganttInstance = useRef(null);
const eventMarkerDay1 = new Date('04/02/2024');
const editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true,
};
const toolbar = ["Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"];
const timelineSettings = {
showTooltip: true,
topTier: {
unit: "Week",
format: "dd/MM/yyyy",
},
bottomTier: {
unit: "Day",
count: 1,
},
};
const labelSettings = {
taskLabel: '${Progress}%'
};
const projectStartDate = new Date("03/31/2024");
const projectEndDate = new Date("05/30/2024");
const splitterSettings = {
columnIndex: 4
};
const selectionSettings = {
mode: "Row",
type: "Single",
enableToggle: false,
};
const tooltipSettings = {
showTooltip: true,
};
const filterSettings = {
type: "Menu",
};
return (
<div>
<GanttComponent
id="EnableWbs"
taskFields={taskFields}
ref={ganttInstance}
toolbar={toolbar}
treeColumnIndex={2}
dataSource={data}
allowSorting={true}
enableContextMenu={true}
enableWBS={true}
enableAutoWbsUpdate={true}
editSettings={editSettings}
allowSelection={true}
allowPdfExport={true}
splitterSettings={splitterSettings}
selectionSettings={selectionSettings}
tooltipSettings={tooltipSettings}
filterSettings={filterSettings}
timelineSettings={timelineSettings}
highlightWeekends={true}
allowFiltering={true}
gridLines={"Both"}
labelSettings={labelSettings}
taskbarHeight={20}
rowHeight={40}
height={"550px"}
allowUnscheduledTasks={true}
projectStartDate={projectStartDate}
projectEndDate={projectEndDate}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" visible={false} />
<ColumnDirective field="WBSCode" width='150px' />
<ColumnDirective field="TaskName" headerText="Task Name" allowReordering={false} width='260px' />
<ColumnDirective field="StartDate" headerText="Start Date" width='140px' />
<ColumnDirective field="WBSPredecessor" headerText="WBS Predecessor" width='190px' />
<ColumnDirective field="Duration" headerText="Duration" allowEditing={false} width='130px' />
<ColumnDirective field="Progress" headerText="Progress" />
</ColumnsDirective>
<EventMarkersDirective>
<EventMarkerDirective day={eventMarkerDay1} label='Project Initiation'></EventMarkerDirective>
</EventMarkersDirective>
<Inject services={[Selection, DayMarkers, Toolbar, Edit, Filter, Sort, ContextMenu]} />
</GanttComponent>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import {
GanttComponent,
Inject,
Selection,
ColumnsDirective,
ColumnDirective,
Toolbar,
DayMarkers,
Edit,
Filter,
Sort,
ContextMenu,
EventMarkersDirective,
EventMarkerDirective
} from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
endDate: "EndDate",
duration: "Duration",
progress: "Progress",
dependency: "Predecessor",
parentID: 'ParentId'
};
let ganttInstance = useRef(null);
const eventMarkerDay1 = new Date('04/02/2024');
const editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true,
};
const toolbar = ["Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"];
const timelineSettings = {
showTooltip: true,
topTier: {
unit: "Week",
format: "dd/MM/yyyy",
},
bottomTier: {
unit: "Day",
count: 1,
},
};
const labelSettings = {
taskLabel: '${Progress}%'
};
const projectStartDate = new Date("03/31/2024");
const projectEndDate = new Date("05/30/2024");
const splitterSettings = {
columnIndex: 4
};
const selectionSettings = {
mode: "Row",
type: "Single",
enableToggle: false,
};
const tooltipSettings = {
showTooltip: true,
};
const filterSettings = {
type: "Menu",
};
return (
<div>
<GanttComponent
id="EnableWbs"
taskFields={taskFields}
ref={ganttInstance}
toolbar={toolbar}
treeColumnIndex={2}
dataSource={data}
allowSorting={true}
enableContextMenu={true}
enableWBS={true}
enableAutoWbsUpdate={true}
editSettings={editSettings}
allowSelection={true}
allowPdfExport={true}
splitterSettings={splitterSettings}
selectionSettings={selectionSettings}
tooltipSettings={tooltipSettings}
filterSettings={filterSettings}
timelineSettings={timelineSettings}
highlightWeekends={true}
allowFiltering={true}
gridLines={"Both"}
labelSettings={labelSettings}
taskbarHeight={20}
rowHeight={40}
height={"550px"}
allowUnscheduledTasks={true}
projectStartDate={projectStartDate}
projectEndDate={projectEndDate}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" visible={false} />
<ColumnDirective field="WBSCode" width='150px' />
<ColumnDirective field="TaskName" headerText="Task Name" allowReordering={false} width='260px' />
<ColumnDirective field="StartDate" headerText="Start Date" width='140px' />
<ColumnDirective field="WBSPredecessor" headerText="WBS Predecessor" width='190px' />
<ColumnDirective field="Duration" headerText="Duration" allowEditing={false} width='130px' />
<ColumnDirective field="Progress" headerText="Progress" />
</ColumnsDirective>
<EventMarkersDirective>
<EventMarkerDirective day={eventMarkerDay1} label='Project Initiation'></EventMarkerDirective>
</EventMarkersDirective>
<Inject services={[Selection, DayMarkers, Toolbar, Edit, Filter, Sort, ContextMenu]} />
</GanttComponent>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/30.2.4/material.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>
Managing WBS code updates
For better performance, you can control when WBS codes are updated by using the actionBegin
and dataBound
events. This is particularly useful during actions like dragging and dropping rows.
In the following example, WBS auto-update is enabled only during the row drag and drop action using these events.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Selection, ColumnsDirective, ColumnDirective, Toolbar, DayMarkers, Edit, Filter, Sort, ContextMenu, EventMarkersDirective, EventMarkerDirective, RowDD } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
import { useRef } from 'react';
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
endDate: "EndDate",
duration: "Duration",
progress: "Progress",
dependency: "Predecessor",
parentID: 'ParentId'
};
let ganttInstance = useRef(null);
const isRowDropped = useRef(false);
const eventMarkerDay1 = new Date('04/02/2024');
const editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true,
};
const toolbar = ["Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"];
const timelineSettings = {
showTooltip: true,
topTier: {
unit: "Week",
format: "dd/MM/yyyy",
},
bottomTier: {
unit: "Day",
count: 1,
},
};
const labelSettings = {
taskLabel: '${Progress}%'
};
const projectStartDate = new Date("03/31/2024");
const projectEndDate = new Date("05/30/2024");
const splitterSettings = {
columnIndex: 4
};
const dataBound = () => {
if (isRowDropped.current) {
ganttInstance.current.enableAutoWbsUpdate = false;
isRowDropped.current = false;
}
};
const actionBegin = (args) => {
if (args.requestType === "rowDropped") {
isRowDropped.current = true;
ganttInstance.current.enableAutoWbsUpdate = false;
}
};
const selectionSettings = {
mode: "Row",
type: "Single",
enableToggle: false,
};
const tooltipSettings = {
showTooltip: true,
};
const filterSettings = {
type: "Menu",
};
return (
<div>
<GanttComponent
id="EnableWbs"
taskFields={taskFields}
ref={ganttInstance}
toolbar={toolbar}
treeColumnIndex={2}
dataSource={data}
allowSorting={true}
enableContextMenu={true}
enableWBS={true}
allowRowDragAndDrop={true}
actionBegin={actionBegin.bind(this)}
dataBound={dataBound.bind(this)}
enableAutoWbsUpdate={false}
editSettings={editSettings}
allowSelection={true}
allowPdfExport={true}
splitterSettings={splitterSettings}
selectionSettings={selectionSettings}
tooltipSettings={tooltipSettings}
filterSettings={filterSettings}
timelineSettings={timelineSettings}
highlightWeekends={true}
allowFiltering={true}
gridLines={"Both"}
labelSettings={labelSettings}
taskbarHeight={20}
rowHeight={40}
height={"550px"}
allowUnscheduledTasks={true}
projectStartDate={projectStartDate}
projectEndDate={projectEndDate}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" visible={false} />
<ColumnDirective field="WBSCode" width='150px' />
<ColumnDirective field="TaskName" headerText="Task Name" allowReordering={false} width='260px' />
<ColumnDirective field="StartDate" headerText="Start Date" width='140px' />
<ColumnDirective field="WBSPredecessor" headerText="WBS Predecessor" width='190px' />
<ColumnDirective field="Duration" headerText="Duration" allowEditing={false} width='130px' />
<ColumnDirective field="Progress" headerText="Progress" />
</ColumnsDirective>
<EventMarkersDirective>
<EventMarkerDirective day={eventMarkerDay1} label='Project Initiation'></EventMarkerDirective>
</EventMarkersDirective>
<Inject services={[Selection, DayMarkers, Toolbar, Edit, Filter, Sort, ContextMenu, RowDD]} />
</GanttComponent>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import {
GanttComponent,
Inject,
Selection,
ColumnsDirective,
ColumnDirective,
Toolbar,
DayMarkers,
Edit,
Filter,
Sort,
ContextMenu,
EventMarkersDirective,
EventMarkerDirective
} from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
const taskFields = {
id: "TaskID",
name: "TaskName",
startDate: "StartDate",
endDate: "EndDate",
duration: "Duration",
progress: "Progress",
dependency: "Predecessor",
parentID: 'ParentId'
};
let ganttInstance = useRef(null);
const isRowDropped = useRef(false);
const eventMarkerDay1 = new Date('04/02/2024');
const editSettings = {
allowAdding: true,
allowEditing: true,
allowDeleting: true,
allowTaskbarEditing: true,
showDeleteConfirmDialog: true,
};
const toolbar = ["Add", "Edit", "Update", "Delete", "Cancel", "ExpandAll", "CollapseAll"];
const timelineSettings = {
showTooltip: true,
topTier: {
unit: "Week",
format: "dd/MM/yyyy",
},
bottomTier: {
unit: "Day",
count: 1,
},
};
const labelSettings = {
taskLabel: '${Progress}%'
};
const projectStartDate = new Date("03/31/2024");
const projectEndDate = new Date("05/30/2024");
const splitterSettings = {
columnIndex: 4
};
const dataBound = () => {
if (isRowDropped.current) {
ganttInstance.current.enableAutoWbsUpdate = false;
isRowDropped.current = false;
}
};
const actionBegin = (args) => {
if (args.requestType === "beforeDrop") {
isRowDropped.current = true;
ganttInstance.current.enableAutoWbsUpdate = false;
}
};
const selectionSettings = {
mode: "Row",
type: "Single",
enableToggle: false,
};
const tooltipSettings = {
showTooltip: true,
};
const filterSettings = {
type: "Menu",
};
return (
<div>
<GanttComponent
id="EnableWbs"
taskFields={taskFields}
ref={ganttInstance}
toolbar={toolbar}
treeColumnIndex={2}
dataSource={data}
allowSorting={true}
enableContextMenu={true}
enableWBS={true}
dataBound={dataBound.bind(this)}
actionBegin={actionBegin.bind(this)}
enableAutoWbsUpdate={false}
editSettings={editSettings}
allowSelection={true}
allowPdfExport={true}
splitterSettings={splitterSettings}
selectionSettings={selectionSettings}
tooltipSettings={tooltipSettings}
filterSettings={filterSettings}
timelineSettings={timelineSettings}
highlightWeekends={true}
allowFiltering={true}
gridLines={"Both"}
labelSettings={labelSettings}
taskbarHeight={20}
rowHeight={40}
height={"550px"}
allowUnscheduledTasks={true}
projectStartDate={projectStartDate}
projectEndDate={projectEndDate}
>
<ColumnsDirective>
<ColumnDirective field="TaskID" visible={false} />
<ColumnDirective field="WBSCode" width='150px' />
<ColumnDirective field="TaskName" headerText="Task Name" allowReordering={false} width='260px' />
<ColumnDirective field="StartDate" headerText="Start Date" width='140px' />
<ColumnDirective field="WBSPredecessor" headerText="WBS Predecessor" width='190px' />
<ColumnDirective field="Duration" headerText="Duration" allowEditing={false} width='130px' />
<ColumnDirective field="Progress" headerText="Progress" />
</ColumnsDirective>
<EventMarkersDirective>
<EventMarkerDirective day={eventMarkerDay1} label='Project Initiation'></EventMarkerDirective>
</EventMarkersDirective>
<Inject services={[Selection, DayMarkers, Toolbar, Edit, Filter, Sort, ContextMenu]} />
</GanttComponent>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/30.2.4/material.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>
Limitations
The WBS feature has a few limitations in the React Gantt component:
- Editing of the WBS code and WBS predecessor columns is not supported.
- Load on demand is not supported with the WBS feature.
- WBS Code and WBS Predecessor fields cannot be mapped directly from the data source.