Maintain Zoom-to-fit in React Gantt Chart Component
18 Nov 201815 minutes to read
The zoom-to-fit functionality in the React Gantt Chart component ensures the entire project timeline fits within the viewport, providing an optimal view of all tasks. When using the zoomToFit toolbar item, editing actions (e.g., cell edit, dialog edit, taskbar edit) or dynamic dataSource changes can cause the timeline to refresh, potentially losing the zoomed view. By leveraging the fitToProject method, you can maintain the zoom-to-fit state seamlessly. For editing actions, call fitToProject in the actionComplete and taskbarEdited events to reapply zoom-to-fit after modifications like updating task durations or dependencies. For dynamic dataSource changes, such as adding or removing tasks, invoke fitToProject in the dataBound event to adjust the timeline automatically. Ensure ToolbarService is injected and toolbar includes zoomToFit to enable this feature, with valid timelineSettings configured for accurate rendering. This approach maintains a consistent project overview, integrating with task scheduling, dependencies, and critical path for efficient project management.
The following example demonstrates how to use fitToProject after performing edit actions:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Edit, Selection, Toolbar } 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'
};
const toolbar = ['Edit', 'ZoomToFit'];
const editSettings = {
allowEditing: true,
allowTaskbarEditing: true
};
let ganttInstance;
function actionComplete(args) {
if ((args.action === 'CellEditing' || args.action === 'DialogEditing') && args.requestType === 'save') {
if (ganttInstance) {
ganttInstance.dataSource = data;
ganttInstance.fitToProject();
}
}
}
function taskbarEdited(args) {
if (args && ganttInstance) {
ganttInstance.dataSource = data;
ganttInstance.fitToProject();
}
}
return (
<GanttComponent
ref={g => ganttInstance = g}
id="ganttDefault"
height="430px"
dataSource={data}
taskFields={taskFields}
toolbar={toolbar}
editSettings={editSettings}
actionComplete={actionComplete}
taskbarEdited={taskbarEdited}>
<Inject services={[Edit, Selection, Toolbar]} />
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Edit, Selection, Toolbar, ActionCompleteArgs, ITaskbarEditedEventArgs, EditSettingsModel, ToolbarItem, TaskFieldsModel } from '@syncfusion/ej2-react-gantt';
import { data } from './datasource';
function App() {
const taskFields: TaskFieldsModel = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
parentID: 'ParentID'
};
const toolbar: ToolbarItem[] = ['Edit', 'ZoomToFit'];
const editSettings: EditSettingsModel = {
allowEditing: true,
allowTaskbarEditing: true
};
let ganttInstance: GanttComponent | null;
function actionComplete(args: ActionCompleteArgs): void {
if ((args.action === 'CellEditing' || args.action === 'DialogEditing') && args.requestType === 'save') {
if (ganttInstance) {
ganttInstance.dataSource = data;
ganttInstance.fitToProject();
}
}
}
function taskbarEdited(args: ITaskbarEditedEventArgs): void {
if (args && ganttInstance) {
ganttInstance.dataSource = data;
ganttInstance.fitToProject();
}
}
return (
<GanttComponent
ref={g => ganttInstance = g}
id="ganttDefault"
height="430px"
dataSource={data}
taskFields={taskFields}
toolbar={toolbar}
editSettings={editSettings}
actionComplete={actionComplete}
taskbarEdited={taskbarEdited}>
<Inject services={[Edit, Selection, Toolbar]} />
</GanttComponent>
);
}
ReactDOM.render(<App />, document.getElementById('root'));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>The following example demonstrates how to use fitToProject after dynamically changing the data source:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Toolbar, ToolbarItem }from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { data, changeData } from './datasource';
function App(){
let ganttInstance;
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
parentID: 'ParentId'
};
const toolbarOptions = ['ZoomToFit'];
function clickHandler() {
ganttInstance.dataSource = changeData;
};
function dataBound(args) {
ganttInstance.fitToProject();
};
return (<div>
<ButtonComponent onClick= { clickHandler}>Change Data</ButtonComponent>
<GanttComponent
dataSource={data}
taskFields={taskFields}
dataBound={dataBound}
toolbar={toolbarOptions}
height = '450px'
ref={gantt => ganttInstance = gantt}
>
<Inject services={[Toolbar]} />
</GanttComponent></div>)
};
ReactDOM.render(<App />, document.getElementById('root'));import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { GanttComponent, Inject, Toolbar, ToolbarItem }from '@syncfusion/ej2-react-gantt';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { data, changeData } from './datasource';
function App(){
let ganttInstance: any;
const taskFields: any = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Predecessor',
parentID: 'ParentId'
};
const toolbarOptions: ToolbarItem[] = ['ZoomToFit'];
function clickHandler() {
ganttInstance.dataSource = changeData;
};
function dataBound(args) {
ganttInstance.fitToProject();
};
return (
<div>
<ButtonComponent onClick= { clickHandler}>Change Data</ButtonComponent>
<GanttComponent
dataSource={data}
taskFields={taskFields}
dataBound={dataBound}
toolbar={toolbarOptions}
height = '450px'
ref={gantt => ganttInstance = gantt}
>
<Inject services={[Toolbar]} />
</GanttComponent>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React Gantt</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/34.1.29/tailwind3.css" rel="stylesheet" type="text/css"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<style>
#loader {
color: #008cff;
height: 40px;
left: 45%;
position: absolute;
top: 45%;
width: 30%;
}
</style>
</head>
<body>
<div id='root'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>