Skip to main content

Editor

The task editor dialog allows you to configure a set of fields (controls) for viewing and editing task data. The task editor modal dialog consists of configurable fields for managing task data.

Basic setup​

To use the task editor, import both Gantt and a standalone Editor component based on SVAR Editor from @svar-ui/react-gantt and pass the api reference to both:

import { useState } from "react";
import { Gantt, Editor } from "@svar-ui/react-gantt";

function App() {
const [api, setApi] = useState(null);

return (
<>
<Gantt ref={setApi} />
{api && <Editor api={api} />}
</>
);
}

Configuring the Editor​

To define the editor fields, use the items property of the standalone Editor component.

Supported editor field types include:

  • text and textarea
  • date
  • slider
  • select
  • counter
  • links

For example, to define a simple text input field, add its name to the comp field:

import { useState } from "react";
import { Gantt, Editor } from "@svar-ui/react-gantt";

function App() {
const [api, setApi] = useState(null);

const items = [
{
key: "text",
comp: "text",
label: "Name",
config: {
placeholder: "Add task name"
},
},
];

return (
<>
<Gantt ref={setApi} />
{api && <Editor api={api} items={items} />}
</>
);
}

To configure the default editor fields, import the getEditorItems helper to get the default array, modify it as needed, and pass the updated array to the Editor component via the items prop.

The example below shows how to remove the Description field (which uses the key "details") from the editor:

import { useState } from "react";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";

function App() {
const [api, setApi] = useState(null);

const items = getEditorItems().filter(item => item.key !== "details");

return (
<>
<Gantt ref={setApi} />
{api && <Editor api={api} items={items} />}
</>
);
}

The next example demonstrates how to selectively use specific fields from default array to configure a custom editor layout, and how to customize the editor's bottom toolbar with Save/Delete/Close buttons.

import { useState } from "react";
import { getData } from "../data";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";

function App() {
const [api, setApi] = useState(null);
const data = getData();

// Define only the fields you want to include
const keys = ["text", "type", "start", "end", "duration", "progress", "details"];
const allItems = getEditorItems();
const items = keys.map(key => allItems.find(op => op.key === key));

const bottomBar = {
items: [
{ comp: "button", type: "secondary", text: "Close", id: "close" },
{ comp: "spacer" },
{ comp: "button", type: "danger", text: "Delete", id: "delete" },
{ comp: "button", type: "primary", text: "Save", id: "save" },
],
};

return (
<>
<Gantt ref={setApi} tasks={data.tasks} links={data.links} scales={data.scales} />
{api && <Editor api={api} items={items} bottomBar={bottomBar} topBar={false} placement="modal" />}
</>
);
}

The next example demonstrates how to enable the TimePicker for comp: "date":

import { useState } from "react";
import { getData } from "../data";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";

function App() {
const { tasks, links, scales } = getData("hour");
const [api, setApi] = useState(null);

const items = getEditorItems().map(ed => ({
...ed,
...(ed.comp === "date" && { config: { time: true } }),
}));

return (
<>
<Gantt
ref={setApi}
tasks={tasks}
links={links}
scales={scales}
cellWidth={40}
durationUnit={"hour"}
/>
{api && <Editor api={api} items={items} />}
</>
);
}

Resources tab​

PRO

The functionality is available in PRO Edition only

When resources are passed to <Gantt>, the Editor automatically includes a Resources tab. No extra configuration is needed:

import { useState } from "react";
import { getData } from "./common/data";
import { Gantt, Editor } from "@svar/react-gantt";

const { tasks, links, scales, resources, assignments } = getData();

function App() {
const [api, setApi] = useState(null);

return (
<>
<Gantt ref={setApi} tasks={tasks} links={links} scales={scales} resources={resources} assignments={assignments} />
{api && <Editor api={api} />}
</>
);
}

The Resources tab lets users assign resources to the task, adjust allocation, and remove assignments. It is hidden automatically for summary tasks.

For the full resources setup including the inline grid column, see Assign resources.

Scheduling tab​

PRO

The functionality is available in PRO Edition only

The Editor adds the Scheduling tab when at least one of the following Gantt properties is set. The tab shows only the fields of the enabled features:

  • schedule with auto: true adds the Constraint field and the Manual checkbox
  • criticalPath adds the Constraint field
  • deadlines adds the Deadline field
  • inactiveTasks adds the Inactive checkbox
  • schedule with resourceCalendars: true adds the Skip resource calendars checkbox

Some fields are hidden for certain tasks: Constraint and Skip resource calendars are not shown for summary tasks and segments, Manual and Inactive are not shown for segments. The tab is shown only if the task has at least one applicable field. For example, if only criticalPath is set, summary tasks have no Scheduling tab.

No extra Editor configuration is needed:

import { useState } from "react";
import { getData } from "./common/data";
import { Gantt, Editor } from "@svar/react-gantt";

const { tasks, links, scales } = getData();

function App() {
const [api, setApi] = useState(null);

return (
<>
<Gantt
ref={setApi}
tasks={tasks}
links={links}
scales={scales}
schedule={{ auto: true }}
deadlines={true}
inactiveTasks={true}
/>
{api && <Editor api={api} />}
</>
);
}

For details on each field, see Auto scheduling, Constraints, Deadlines, Inactive tasks, and Resource calendars.

Segments tab​

PRO

The functionality is available in PRO Edition only

When splitTasks is enabled, the Editor adds the Segments tab. The tab is shown only for tasks that have segments. It lists the segments of the task in a grid where users can edit the name, start date, and duration of each segment, or delete it. When the last segment is removed, the tab disappears (with autoSave={false}, after the changes are saved).

For the full split tasks setup, see Managing split tasks.

Custom controls​

You can extend the task editor with custom React components using the registerEditorItem helper. A registered component can then be used as an editor field via the comp property.

The custom component must support value property and onChange callback.

The example below shows how to register a radio button group component and use it as Type field in the editor:

import { useState } from "react";
import { getData } from "../data";
import { Gantt, Editor, getEditorItems, registerEditorItem, defaultTaskTypes } from "@svar-ui/react-gantt";
import { RadioButtonGroup } from "@svar-ui/react-core";

registerEditorItem("radio", RadioButtonGroup);

// replace the "type" select with a radio group
const items = getEditorItems().map(item =>
item.key === "type"
? {
key: "type",
comp: "radio",
label: "Type",
options: defaultTaskTypes.map(o => ({
...o,
value: o.id,
})),
config: { type: "inline" },
}
: item
);

const data = getData();

function App() {
const [api, setApi] = useState(null);

return (
<>
<Gantt ref={setApi} tasks={data.tasks} links={data.links} scales={data.scales} />
{api && <Editor api={api} items={items} />}
</>
);
}

Related sample: Editor: custom controls

Comments​

You can add a comments section to the task editor using the Comments component from the @svar-ui/react-comments package.

Step 1. Register the Comments component as a custom editor control:

import { registerEditorItem } from "@svar-ui/react-gantt";
import { Comments } from "@svar-ui/react-comments";

registerEditorItem("comments", Comments);

Step 2. Add a comments array to each task in your data. Each comment object requires the following fields:

  • id — unique comment ID
  • user — ID of the user who left the comment
  • content — comment text
  • date — comment date
const data = getData();

data.tasks.forEach(task => {
task.comments = [];
});

// Example with initial comments on the first task:
data.tasks[0].comments = [
{ id: 1, user: 1, content: "Let's tackle at least half of the plan items soon.", date: new Date() },
{ id: 2, user: 2, content: "Agreed, let's execute efficiently.", date: new Date() },
];

Step 3. Add the comments field to the editor items and pass a users list and the activeUser ID:

import { useState } from "react";
import { Gantt, Editor, getEditorItems, registerEditorItem } from "@svar-ui/react-gantt";
import { Comments } from "@svar-ui/react-comments";
import { getData } from "./common/data";

registerEditorItem("comments", Comments);

const data = getData();

// add a `comments` array to each task (see Step 2)

const keys = ["text", "details"];
const items = getEditorItems().filter(op => keys.includes(op.key));
items.push({
key: "comments",
comp: "comments",
label: "Comments",
users: [
{ id: 1, name: "Alex" },
{ id: 2, name: "John" },
{ id: 3, name: "Bob" },
],
activeUser: 1,
});

function App() {
const [api, setApi] = useState(null);

return (
<>
<Gantt ref={setApi} tasks={data.tasks} links={data.links} />
{api && <Editor api={api} items={items} />}
</>
);
}

Related sample: Editor: custom comments

Tasklist​

You can embed a checklist inside the task editor using the Tasklist component from the @svar-ui/react-tasklist package.

Step 1. Register the Tasklist component as a custom editor control:

import { registerEditorItem } from "@svar-ui/react-gantt";
import { Tasklist } from "@svar-ui/react-tasklist";

registerEditorItem("tasks", Tasklist);

Step 2. Add a tasks array to each task in your data. Each item requires:

  • id — unique item ID
  • content — item description text
  • status — 1 for completed, 0 for incomplete
  • date — (optional) item date
const data = getData();

data.tasks.forEach(task => {
task.tasks = [];
});

// Example with initial checklist items on the first task:
data.tasks[0].tasks = [
{ id: 1, content: "Research best practices for the integration", status: 1 },
{ id: 2, content: "Explore modern approaches to building the app", status: 0 },
{ id: 3, content: "Optimize performance", status: 0 },
];

Step 3. Add the task list field to the editor items:

import { useState } from "react";
import { Gantt, Editor, getEditorItems, registerEditorItem } from "@svar-ui/react-gantt";
import { Tasklist } from "@svar-ui/react-tasklist";
import { getData } from "./common/data";

registerEditorItem("tasks", Tasklist);

const data = getData();

// add a `tasks` array to each task (see Step 2)

const keys = ["text", "details"];
const items = getEditorItems().filter(op => keys.includes(op.key));
items.push({
key: "tasks",
comp: "tasks",
label: "Tasks",
});

function App() {
const [api, setApi] = useState(null);

return (
<>
<Gantt ref={setApi} tasks={data.tasks} links={data.links} />
{api && <Editor api={api} items={items} />}
</>
);
}

Related sample: Editor: custom tasks

Validation​

You can add validation rules to editor fields by extending the items returned from getEditorItems(). Set autoSave={false} on the Editor component so that validation runs before the task is saved.

Each field supports the following validation properties:

  • required — marks the field as required; the editor will block saving if the field is empty
  • validation — a function (value) => boolean that returns true if the value is valid
  • validationMessage — the error message shown when validation returns false
import { useState } from "react";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";
import { getData } from "./common/data";

function App() {
const [api, setApi] = useState(null);
const data = getData();

const items = getEditorItems().map(ed => ({
...ed,
...(ed.comp === "text" && { required: true }),
...(ed.comp === "counter" && {
validation: v => v <= 50,
validationMessage: "Task duration should not exceed 50 days",
}),
}));

return (
<>
<Gantt ref={setApi} tasks={data.tasks} links={data.links} scales={data.scales} />
{api && <Editor api={api} items={items} autoSave={false} />}
</>
);
}

In this example:

  • The task name field (comp: "text") is required
  • The duration field (comp: "counter") must not exceed 50 days

Related sample: Editor: validation

Custom editor dialog​

To add your custom editor, you should:

  • Import the custom Form component for adding/editing tasks
  • Use the api.intercept method to disable opening the default editor by blocking the show-editor action (return false)
  • Add the Form tag, define tasks and taskTypes, and add the action handler function that triggers the update-task or delete-task action.
import { useState } from "react";
import { getData } from "../data";
import { Gantt } from "@svar-ui/react-gantt";
import Form from "../custom/Form.jsx";

function App() {
const data = getData();
const taskTypes = [
{ id: "task", label: "Task" },
{ id: "milestone", label: "Milestone" },
{ id: "summary", label: "Project" },
];

const [task, setTask] = useState(null);
const [gApi, setGApi] = useState(null);

const init = (api) => {
setGApi(api);
api.intercept("show-editor", ({ id }) => {
if (id) setTask(api.getState().tasks.byId(id));
return false;
});
};

const formAction = ({ action, data }) => {
switch (action) {
case "close-form":
setTask(null);
break;
default:
gApi.exec(action, data); // "update-task", "delete-task" actions
break;
}
};

return (
<>
<Gantt
tasks={data.tasks}
links={data.links}
scales={data.scales}
init={init}
/>

{task && (
<Form task={task} taskTypes={taskTypes} onAction={formAction} />
)}
</>
);
}

Related sample: Custom edit form

Read-only editor​

You can set the Editor to readonly to allow users to view task data without being able to edit it. Pass the readonly prop to the Editor component:

<Gantt ref={setApi} tasks={data.tasks} links={data.links} scales={data.scales} />
<Editor api={api} readonly />

This affects only the editor dialog. To make the entire Gantt chart non-interactive, use the Gantt-level readonly property instead.

Related sample: