Syncfusion AI Assistant

How can I help you?

Configure custom fields in React Gantt Chart Component

12 Mar 202617 minutes to read

The React Gantt Chart component allows you to enhance task data management by adding custom fields to the add/edit dialogs, seamlessly integrating them into the General tab using the actionBegin and actionComplete events. For example, adding a priority dropdown to the General tab enables users to assign task priorities during creation or editing. Inject Edit service and enable editSettings.allowAdding and editSettings.allowEditing to support dialog modifications. Configure valid taskFields mappings or custom data properties (e.g., priority) to persist custom field values in the data source. Use actionBegin to define custom field properties (e.g., textbox, dropdown) before the dialog opens, and actionComplete to handle field data after user input. This feature supports various field types, such as dropdowns or numerics, and integrates with task scheduling, dependencies, and critical path, ensuring custom fields align with project workflows. Ensure the dialog module is configured to render custom fields accurately, enhancing flexibility in task management.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { GanttComponent, Inject, Edit, Selection, Toolbar } from "@syncfusion/ej2-react-gantt";
import { CheckBox } from "@syncfusion/ej2-buttons";
import { TextBox, NumericTextBox, MaskedTextBox } from "@syncfusion/ej2-inputs";
import { DatePicker, DateTimePicker } from "@syncfusion/ej2-calendars";
import { DropDownList } from "@syncfusion/ej2-dropdowns";

import { data } from "./datasource";

function App() {

  let ganttInstance = null;
  let divElement = null;

  const inputs = {
    booleanedit: CheckBox,
    dropdownedit: DropDownList,
    datepickeredit: DatePicker,
    datetimepickeredit: DateTimePicker,
    maskededit: MaskedTextBox,
    numericedit: NumericTextBox,
    stringedit: TextBox
  };

  const taskSettings = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    endDate: "EndDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const editSettings = {
    allowEditing: true,
    allowAdding: true,
    allowDeleting: true,
    mode: "Dialog"
  };

  const editDialogFields = [
    { type: "General", headerText: "General" },
    { type: "Dependency" },
    { type: "Resources" },
    { type: "Notes" }
  ];

  const addDialogFields = [
    { type: "General", headerText: "General" },
    { type: "Dependency" },
    { type: "Resources" },
    { type: "Notes" }
  ];

  const columns = [
    { field: "TaskID", headerText: "Task ID", textAlign: "Left", width: "100" },
    { field: "TaskName", headerText: "Task Name", width: "250" },
    { field: "StartDate", headerText: "Start Date", width: "150" },
    { field: "EndDate", headerText: "End Date", width: "150" },
    { field: "Duration", headerText: "Duration", width: "150" },
    { field: "Progress", headerText: "Progress", width: "150" },
    { field: "Priority", headerText: "Custom Field", width: "150" }
  ];

  const toolbar = [
    "Add",
    "Edit",
    "Delete",
    "Update",
    "Cancel",
    "ExpandAll",
    "CollapseAll"
  ];

  function actionBegin(args) {
    if (args.requestType === "beforeOpenEditDialog" ||
      args.requestType === "beforeOpenAddDialog") {

      const column = ganttInstance.columnByField["Priority"];

      divElement = ganttInstance.createElement("div", {
        className: "e-edit-form-column"
      });

      const inputElement = ganttInstance.createElement("input", {
        attrs: {
          type: "text",
          id: ganttInstance.controlId + column.field,
          name: column.field,
          title: column.field
        }
      });

      divElement.appendChild(inputElement);

      const inputOptions = {
        enabled: true,
        floatLabelType: "Auto",
        placeholder: "Priority",
        value: (args.rowData).Priority
      };

      const editorType = inputs[column.editType];
      const inputObj = new editorType(inputOptions);
      inputObj.appendTo(inputElement);
    }
  }

  function actionComplete(args) {
    if (args.requestType === "openEditDialog" ||
      args.requestType === "openAddDialog") {

      const generalTab = document.getElementById(
        ganttInstance.controlId + "GeneralTabContainer"
      );

      if (generalTab && divElement) {
        generalTab.appendChild(divElement);
      }
    }
  }

  return (
    <GanttComponent
      height="430px"
      dataSource={data}
      taskFields={taskSettings}
      editSettings={editSettings}
      editDialogFields={editDialogFields}
      addDialogFields={addDialogFields}
      columns={columns}
      toolbar={toolbar}
      actionBegin={actionBegin}
      actionComplete={actionComplete}
      ref={(g) => (ganttInstance = g)}
    >
      <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, ToolbarItem, ActionBeginArgs, ActionCompleteArgs, TaskFieldsModel, EditSettingsModel, Columns } from "@syncfusion/ej2-react-gantt";
import { CheckBox } from "@syncfusion/ej2-buttons";
import { TextBox, NumericTextBox, MaskedTextBox } from "@syncfusion/ej2-inputs";
import { DatePicker, DateTimePicker } from "@syncfusion/ej2-calendars";
import { DropDownList } from "@syncfusion/ej2-dropdowns";

import { data } from "./datasource";

function App() {

  let ganttInstance: GanttComponent | null = null;
  let divElement: HTMLElement | null = null;

  const inputs: any = {
    booleanedit: CheckBox,
    dropdownedit: DropDownList,
    datepickeredit: DatePicker,
    datetimepickeredit: DateTimePicker,
    maskededit: MaskedTextBox,
    numericedit: NumericTextBox,
    stringedit: TextBox
  };

  const taskSettings: TaskFieldsModel = {
    id: "TaskID",
    name: "TaskName",
    startDate: "StartDate",
    endDate: "EndDate",
    duration: "Duration",
    progress: "Progress",
    parentID: "ParentID"
  };

  const editSettings: EditSettingsModel = {
    allowEditing: true,
    allowAdding: true,
    allowDeleting: true,
    mode: "Dialog"
  };

  const editDialogFields = [
    { type: "General", headerText: "General" },
    { type: "Dependency" },
    { type: "Resources" },
    { type: "Notes" }
  ];

  const addDialogFields = [
    { type: "General", headerText: "General" },
    { type: "Dependency" },
    { type: "Resources" },
    { type: "Notes" }
  ];

  const columns: Columns[] = [
    { field: "TaskID", headerText: "Task ID", textAlign: "Left", width: "100" },
    { field: "TaskName", headerText: "Task Name", width: "250" },
    { field: "StartDate", headerText: "Start Date", width: "150" },
    { field: "EndDate", headerText: "End Date", width: "150" },
    { field: "Duration", headerText: "Duration", width: "150" },
    { field: "Progress", headerText: "Progress", width: "150" },
    { field: "Priority", headerText: "Custom Field", width: "150" }
  ];

  const toolbar: ToolbarItem[] = [
    "Add",
    "Edit",
    "Delete",
    "Update",
    "Cancel",
    "ExpandAll",
    "CollapseAll"
  ];

  function actionBegin(args: ActionBeginArgs): void {
    if (args.requestType === "beforeOpenEditDialog" ||
      args.requestType === "beforeOpenAddDialog") {

      const column: any = ganttInstance!.columnByField["Priority"];

      divElement = ganttInstance!.createElement("div", {
        className: "e-edit-form-column"
      }) as HTMLElement;

      const inputElement = ganttInstance!.createElement("input", {
        attrs: {
          type: "text",
          id: ganttInstance!.controlId + column.field,
          name: column.field,
          title: column.field
        }
      });

      divElement.appendChild(inputElement as HTMLElement);

      const inputOptions = {
        enabled: true,
        floatLabelType: "Auto",
        placeholder: "Priority",
        value: (args.rowData as any).Priority
      };

      const editorType = inputs[column.editType];
      const inputObj = new editorType(inputOptions);
      inputObj.appendTo(inputElement as HTMLElement);
    }
  }

  function actionComplete(args: ActionCompleteArgs): void {
    if (args.requestType === "openEditDialog" ||
      args.requestType === "openAddDialog") {

      const generalTab = document.getElementById(
        ganttInstance!.controlId + "GeneralTabContainer"
      );

      if (generalTab && divElement) {
        generalTab.appendChild(divElement);
      }
    }
  }

  return (
    <GanttComponent
      height="430px"
      dataSource={data}
      taskFields={taskSettings}
      editSettings={editSettings}
      editDialogFields={editDialogFields}
      addDialogFields={addDialogFields}
      columns={columns}
      toolbar={toolbar}
      actionBegin={actionBegin}
      actionComplete={actionComplete}
      ref={(g) => (ganttInstance = g)}
    >
      <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/33.1.44/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>

See also