Custom Adaptor for Data Binding in React Gantt Chart
The CustomAdaptor in Syncfusion® React Gantt Chart is a powerful extension mechanism that customizes any existing adaptor (RemoteSaveAdaptor, WebMethodAdaptor, ODataV4Adaptor, GraphQLAdaptor) to meet specific application requirements. Instead of creating an adaptor from scratch, CustomAdaptor intercepts and customizes the HTTP request/response pipeline used by the Syncfusion React Gantt Chart.
For detailed guidance, refer to the DataManager CustomAdaptor documentation, which explains the usage of custom adaptors in depth. For complete server-side setup and advanced implementation details, see the DataManager ODataV4Adaptor documentation, covering endpoint configuration, query handling, and recommended practices for integrating OData V4 services.
Once the project creation and backend setup are complete, the next step is to render the Syncfusion® React Gantt Chart component on the client side.
Project structure:
- Frontend: A React project that hosts the Gantt Chart component and configures the Custom DataManager by extending ODataV4Adaptor.
- Backend: An OData v4 service that exposes task entities and supports the query options that client will use.
CustomAdaptor/
├── CustomAdaptor.client/ # React frontend (Vite/React project).
│ ├── src/
│ │ ├── App.css
│ │ ├── App.jsx # Add your CustomAdaptor here.
| | └── CustomAdaptor.jsx # Extend odatav4 adaptor here.
│ └── package.json
└── CustomAdaptor.Server/ # ASP.NET Core backend (API).
├── Controllers/ # API controllers (will be created here).
├── Models/ # Data models (will be created here).
└── Program.cs # Server configuration.
React Gantt Chart setup and client-side configuration
This section explains how the Gantt Chart interacts with a custom adaptor for extending OData v4 services. Implementation and package installation steps are covered in platform-specific setup guides and are intentionally omitted here.
Step 1: Packages and dependencies
- Ensure your React project includes the Syncfusion Gantt Chart and data packages required to render the Gantt Chart and to use the DataManager and ODataV4Adaptor.
- Right-click the CustomAdaptor.client folder in Solution Explorer and select Open in Terminal (available in newer Visual Studio versions), or open a Developer Command prompt/PowerShell from the Start menu and navigate manually to the CustomAdaptor.client directory. Once inside the folder, confirm that package.json is present, then run the following commands to install the required Syncfusion® packages:
npm install @syncfusion/ej2-react-gantt --save
npm install @syncfusion/ej2-data --saveStep 2: CSS and component styling
- Include the required Syncfusion theme and component styles so the Gantt Chart and its input controls render correctly. Add these imports to index.css or App.css:
@import "../node_modules/@syncfusion/ej2-tailwind3-theme/styles/gantt/index.css";Import the App.css in the application entry point (App.jsx).
import "./App.css";
...
...Step 3: Create React Gantt Chart component with CustomAdaptor
Integrating a CustomAdaptor with the Syncfusion® React Gantt Chart requires configuring the DataManager as the communication bridge between the Gantt Chart component and the backend data source. The CustomAdaptor serves as a powerful customization layer that provides complete control over how data operations are transmitted to the server.
Step 3.1: Creating an Extended ODataV4Adaptor
The first step involves creating a custom adaptor by extending the existing ODataV4Adaptor class. This extension allows modification of the default behavior to meet specific application requirements.
Begin by creating a new TypeScript file named CustomAdaptor.jsx in the project’s source directory. This file will house the custom adaptor class definition.
Understanding the CustomAdaptor implementation:
The example below demonstrates a CustomAdaptor class that extends ODataV4Adaptor.
The implementation requires importing specific modules from Syncfusion packages:
-
DataManager,ODataV4Adaptor, andQueryfrom@syncfusion/ej2-data- Core data management classes
The Syncfusion® DataManager provides built-in extensibility points that allow custom logic to be applied both before a request is sent to the server and after a response is received. This is achieved by overriding adaptor methods, ensuring that request customization and response transformation are handled consistently and centrally. The following table explains the overridden methods in a CustomAdaptor and their execution phases.
| Method | Execution Phase | Purpose & Key Actions |
|---|---|---|
processResponse |
After receiving server response, before Gantt Chart rendering | |
processQuery |
Before sending request to server | Sets custom OData endpoint URL and adds extra query parameters → enables dynamic URLs and request tracking/identification |
beforeSend |
Immediately before the HTTP request is sent | Adds Authorization: Bearer header using token from window → automatically authenticates every API request |
import { ODataV4Adaptor, } from '@syncfusion/ej2-data';
export class CustomAdaptor extends ODataV4Adaptor {
processResponse() {
const original = super.processResponse.apply(this, arguments);
return original;
}
processQuery(dm, query) {
dm.dataSource.url = 'https://localhost:7284/odata/GanttTasks';
query.addParams('Syncfusion in React Gantt Chart', 'true');
const result = super.processQuery.apply(this, arguments);
return result;
}
beforeSend(dm, request, settings) {
request.headers.set('Authorization', `Bearer ${(window).token}`);
super.beforeSend(dm, request, settings);
}
}Step 3.2: Integrating CustomAdaptor into React Gantt Chart
After creating the custom adaptor class, integrate it with the React Gantt Chart in the main application file (typically App.tsx or App.jsx). This requires importing the necessary modules and configuring the Gantt Chart to use the custom adaptor:
- Import
DataManagerfrom@syncfusion/ej2-datato act as the link between the Gantt Chart and the OData service. - Import
CustomAdaptorfrom the local ./CustomAdaptor file to apply custom request and response logic. - Create DataManager instance by setting the service endpoint URL (e.g., https://localhost:xxxx/odata/GanttTasks) in the
urlproperty. - Assign
CustomAdaptorto theadaptorproperty so that querying operations use the customized pipeline. - Bind DataManager to the Gantt Chart
dataSourceproperty, enabling the Gantt Chart to automatically apply the custom logic during data communication.
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { CustomAdaptor } from './CustomAdaptor';
import { GanttComponent, Inject, Edit, Selection, Toolbar, ColumnsDirective, ColumnDirective, ContextMenu, Filter, Sort, Reorder, Resize, ColumnMenu, VirtualScroll, RowDD, } from '@syncfusion/ej2-react-gantt';
import './App.css';
function App() {
// Create DataManager with ODataV4Adaptor
const data = new DataManager({
url: 'https://localhost:7284/odata/GanttTasks',
adaptor: new CustomAdaptor(),
key: 'TaskID',
crossDomain: true
});
const resourceFields = {
id: 'resourceId',
name: 'resourceName',
unit: 'resourceUnit',
group: 'resourceGroup'
};
const resources = [
{ resourceId: 1, resourceName: 'Martin Tamer' },
{ resourceId: 2, resourceName: 'Rose Fuller' },
{ resourceId: 3, resourceName: 'Margaret Buchanan' },
{ resourceId: 4, resourceName: 'Fuller King' },
{ resourceId: 5, resourceName: 'Davolio Fuller' },
{ resourceId: 6, resourceName: 'Van Jack' },
{ resourceId: 7, resourceName: 'Fuller Buchanan' },
{ resourceId: 8, resourceName: 'Jack Davolio' },
{ resourceId: 9, resourceName: 'Tamer Vinet' },
{ resourceId: 10, resourceName: 'Vinet Fuller' },
{ resourceId: 11, resourceName: 'Bergs Anton' },
{ resourceId: 12, resourceName: 'Construction Supervisor' }
];
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Dependency',
parentID: 'ParentID',
segments: 'Segments',
resourceInfo: 'ResourceInfos',
};
const editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
allowTaskbarEditing: true
};
const toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Indent', 'Outdent'];
return (
<div style={{ margin: '20px' }}>
<h2>ODataV4Adaptor with Gantt</h2>
<GanttComponent dataSource={data} taskFields={taskFields} resourceFields={resourceFields} resources={resources} showColumnMenu= {true}
editSettings={editSettings} height='400px' toolbar={toolbar} allowReordering={true} allowResizing={true} allowRowDragAndDrop={true} enableContextMenu={true} allowFiltering={true} allowSorting={true}>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" textAlign="Right" width="90" type="number" isPrimaryKey={true} />
<ColumnDirective field="TaskName" headerText="Task Name" textAlign="Left" width="270" type="string" />
<ColumnDirective field="StartDate" headerText="Start Date" textAlign="Right" width="150" format="yMd" type="dateTime" />
<ColumnDirective field="EndDate" headerText="End Date" textAlign="Right" width="150" format="dd/MM/yyyy hh:mm" type="dateTime" />
<ColumnDirective field="Duration" headerText="Duration" textAlign="Right" width="90" type="number" />
<ColumnDirective field="Progress" headerText="Progress" textAlign="Right" width="120" type="number" />
</ColumnsDirective>
<Inject services={[Edit, Selection, Toolbar, ContextMenu, Filter, Sort, Reorder, Resize, ColumnMenu, VirtualScroll, RowDD]} />
</GanttComponent>
</div>
);
}
export default App;Replace https://localhost:xxxx/odata/GanttTasks with the actual API endpoint that returns data in JSON format.
Server-side data operations
When tasks, dependencies or resource assignments are numerous or governed by centralized business rules, the server commonly performs processing that would be costly or inconsistent on the client. For Gantt Chart scenarios, server responsibilities typically include selecting tasks for a requested timeline range, applying visibility rules, resolving dependencies, and producing any roll-up or hierarchical values required by the client. The Syncfusion.EJ2.AspNet.Core package supports this approach by providing built-in methods that efficiently handle these operations on the server, ensuring smooth performance even with heavy data loads.
CRUD operations
The DataManager with Custom Adaptor supports Create (add records), Read (view records), Update (modify records), and Delete (remove records) workflows for task entities. In Gantt Chart usage, these operations cover task creation, task edits (including taskbar edits and resulting scheduling recalculations), dependency creation or modification, and task deletion.
Mapping CRUD operations to service endpoints
CRUD operations are conveyed to the service using standard OData conventions. The CustomAdaptor works with ODataV4Adaptor with a single task endpoint and standard HTTP methods:
| Operation | HTTP Method | URL Example | Description |
|---|---|---|---|
| Read | GET | /odata/GanttTasks |
Get all records. |
| Create | POST | /odata/GanttTasks |
Add a new record. |
| Update | PATCH | /odata/GanttTasks(1) |
Update record with key “1”. |
| Delete | DELETE | /odata/GanttTasks(1) |
Delete record with key “1”. |
Step 1: Complete server-side controller
Add all CRUD methods to the GanttController.cs. Replace the entire controller with this complete version:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Formatter;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using ODataV4Adaptor.Server.Models;
[Route("[controller]")]
public class GanttTasksController : ODataController
{
[EnableQuery]
[HttpGet]
public IActionResult Get()
{
var data = GanttDataAdaptor.GetAllRecords();
return Ok(data.AsQueryable());
}
[HttpPost]
[EnableQuery]
public IActionResult Post([FromBody] GanttDataAdaptor task)
{
if (task == null)
return BadRequest();
GanttDataAdaptor.GetAllRecords().Add(task);
return Created(task);
}
[HttpPatch("{key}")]
[EnableQuery]
public IActionResult Patch([FromODataUri] int key, [FromBody] GanttDataAdaptor updateRecord)
{
var task = GanttDataAdaptor.GetAllRecords()
.FirstOrDefault(t => t.TaskID == key);
if (task == null || task.TaskID != updateRecord.TaskID)
return NotFound();
task = updateRecord;
return Ok(task);
}
[HttpDelete("{key}")]
[EnableQuery]
public IActionResult Delete(int key)
{
var task = GanttDataAdaptor.GetAllRecords()
.FirstOrDefault(t => t.TaskID == key);
if (task == null)
return NotFound();
GanttDataAdaptor.GetAllRecords().Remove(task);
return NoContent();
}
}Step 2: Client-side Gantt Chart configuration
React Gantt Chart enables full CRUD functionality by configuring the required toolbar buttons (Add, Edit, Update, Delete, and Cancel) and enabling adding, editing, updating, and deleting through the editSettings property. This setup allows the Gantt Chart to handle all basic data operations directly from the UI.
import { DataManager, ODataV4Adaptor } from '@syncfusion/ej2-data';
import { CustomAdaptor } from './CustomAdaptor';
import { GanttComponent, Inject, Edit, Selection, Toolbar, ColumnsDirective, ColumnDirective, ContextMenu, Filter, Sort, Reorder, Resize, ColumnMenu, VirtualScroll, RowDD, } from '@syncfusion/ej2-react-gantt';
import './App.css';
function App() {
// Create DataManager with ODataV4Adaptor
const data = new DataManager({
url: 'https://localhost:7284/odata/GanttTasks',
adaptor: new CustomAdaptor(),
key: 'TaskID',
crossDomain: true
});
const resourceFields = {
id: 'resourceId',
name: 'resourceName',
unit: 'resourceUnit',
group: 'resourceGroup'
};
const resources = [
{ resourceId: 1, resourceName: 'Martin Tamer' },
{ resourceId: 2, resourceName: 'Rose Fuller' },
{ resourceId: 3, resourceName: 'Margaret Buchanan' },
{ resourceId: 4, resourceName: 'Fuller King' },
{ resourceId: 5, resourceName: 'Davolio Fuller' },
{ resourceId: 6, resourceName: 'Van Jack' },
{ resourceId: 7, resourceName: 'Fuller Buchanan' },
{ resourceId: 8, resourceName: 'Jack Davolio' },
{ resourceId: 9, resourceName: 'Tamer Vinet' },
{ resourceId: 10, resourceName: 'Vinet Fuller' },
{ resourceId: 11, resourceName: 'Bergs Anton' },
{ resourceId: 12, resourceName: 'Construction Supervisor' }
];
const taskFields = {
id: 'TaskID',
name: 'TaskName',
startDate: 'StartDate',
endDate: 'EndDate',
duration: 'Duration',
progress: 'Progress',
dependency: 'Dependency',
parentID: 'ParentID',
segments: 'Segments',
resourceInfo: 'ResourceInfos',
};
const editSettings = {
allowEditing: true,
allowAdding: true,
allowDeleting: true,
allowTaskbarEditing: true
};
const toolbar = ['Add', 'Edit', 'Update', 'Delete', 'Cancel', 'ExpandAll', 'CollapseAll', 'Indent', 'Outdent'];
return (
<div style={{ margin: '20px' }}>
<h2>ODataV4Adaptor with Gantt</h2>
<GanttComponent dataSource={data} taskFields={taskFields} resourceFields={resourceFields} resources={resources} showColumnMenu= {true}
editSettings={editSettings} height='400px' toolbar={toolbar} allowReordering={true} allowResizing={true} allowRowDragAndDrop={true} enableContextMenu={true} allowFiltering={true} allowSorting={true}>
<ColumnsDirective>
<ColumnDirective field="TaskID" headerText="Task ID" textAlign="Right" width="90" type="number" isPrimaryKey={true} />
<ColumnDirective field="TaskName" headerText="Task Name" textAlign="Left" width="270" type="string" />
<ColumnDirective field="StartDate" headerText="Start Date" textAlign="Right" width="150" format="yMd" type="dateTime" />
<ColumnDirective field="EndDate" headerText="End Date" textAlign="Right" width="150" format="dd/MM/yyyy hh:mm" type="dateTime" />
<ColumnDirective field="Duration" headerText="Duration" textAlign="Right" width="90" type="number" />
<ColumnDirective field="Progress" headerText="Progress" textAlign="Right" width="120" type="number" />
</ColumnsDirective>
<Inject services={[Edit, Selection, Toolbar, ContextMenu, Filter, Sort, Reorder, Resize, ColumnMenu, VirtualScroll, RowDD]} />
</GanttComponent>
</div>
);
}
export default App;For detailed editing setup, refer to the editing documentation.
Run the application
Run the application in Visual Studio, accessible on a URL like https://localhost:xxxx. Verify the API returns data at https://localhost:xxxx/odata/GanttTasks, where xxxx is the port. Gantt Chart displays data fetched from the backend API.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Empty response | Service not returning task records or required metadata | Verify service returns records with fields like parent ids, resources, and start/end dates |
| 404 responses | Incorrect route or endpoint configuration | Confirm DataManager URLs are correct and endpoints exist |
| 500 or server errors | Server-side exceptions or improper request handling | Check server logs, validate parameters, and ensure scheduling/dependency logic is error-free |
| Cross-origin errors | CORS not enabled or misconfiguration | Ensure cross-origin requests are allowed when frontend and backend are on different domains |
| Related data mismatches | Remote datasets not returning expected values | Confirm related endpoints return correct data for display and dependency mapping |
Complete sample repository
For the complete working implementation of this example, refer to the GitHub repository.