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 { useRef } from "react";
import { Gantt, Editor } from "@svar-ui/react-gantt";
function App() {
const api = useRef(null);
return (
<>
<Gantt ref={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 { useRef } from "react";
import { Gantt, Editor } from "@svar-ui/react-gantt";
function App() {
const api = useRef(null);
const items = [
{
key: "text",
comp: "text",
label: "Name",
config: {
placeholder: "Add task name"
},
},
];
return (
<>
<Gantt ref={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 { useRef } from "react";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";
function App() {
const api = useRef(null);
const items = getEditorItems().filter(item => item.key !== "details");
return (
<>
<Gantt ref={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 { useRef } from "react";
import { getData } from "../data";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";
function App() {
const api = useRef(null);
const data = getData();
// Define only the fields you want to include
const keys = ["text", "type", "start", "end", "duration", "progress", "details"];
const items = keys.map(key => getEditorItems().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={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<Editor api={api} items={items} bottomBar={bottomBar} topBar={false} placement="modal" />
</>
);
}
The next example demonstrates how to enable the TimePicker for comp: "date":
import { useRef } from "react";
import { getData } from "../data";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";
function App() {
const { tasks, links } = getData();
const api = useRef(null);
const items = getEditorItems().map(ed => ({
...ed,
...(ed.comp === "date" && { config: { time: true } }),
}));
return (
<>
<Gantt
ref={api}
tasks={tasks}
links={links}
durationUnit={"hour"}
/>
<Editor api={api} items={items} />
</>
);
}
Resources tab
When resources are passed to <Gantt>, the Editor automatically includes a Resources tab. No extra configuration is needed:
import { useRef } from "react";
import { Gantt, Editor } from "@svar-ui/react-gantt";
function App() {
const api = useRef(null);
return (
<>
<Gantt ref={api} tasks={tasks} links={links} scales={scales} resources={resources} assignments={assignments} />
<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.
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 { useRef } from "react";
import { Gantt, Editor, getEditorItems, registerEditorItem } from "@svar-ui/react-gantt";
import { RadioButtonGroup } from "@svar-ui/react-core";
registerEditorItem("radio", RadioButtonGroup);
const items = [
...getEditorItems(),
{
key: "type",
comp: "radio",
label: "Type",
options, // options for radio
type: "inline",
}
];
function App() {
const api = useRef(null);
return (
<>
<Gantt ref={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 @wx/react-comments package.
Step 1. Register the Comments component as a custom editor control:
import { registerEditorItem } from "@svar-ui/react-gantt";
import { Comments } from "@wx/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 IDuser— ID of the user who left the commentcontent— comment textdate— comment date
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 { useRef } from "react";
import { Gantt, Editor, getEditorItems, registerEditorItem } from "@svar-ui/react-gantt";
import { Comments } from "@wx/react-comments";
registerEditorItem("comments", Comments);
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 = useRef(null);
return (
<>
<Gantt ref={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<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 @wx/react-tasklist package.
Step 1. Register the Tasklist component as a custom editor control:
import { registerEditorItem } from "@svar-ui/react-gantt";
import { Tasklist } from "@wx/react-tasklist";
registerEditorItem("tasks", Tasklist);
Step 2. Add a tasks array to each task in your data. Each item requires:
id— unique item IDcontent— item description textstatus—1for completed,0for incompletedate— (optional) item date
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 { useRef } from "react";
import { Gantt, Editor, getEditorItems, registerEditorItem } from "@svar-ui/react-gantt";
import { Tasklist } from "@wx/react-tasklist";
registerEditorItem("tasks", Tasklist);
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 = useRef(null);
return (
<>
<Gantt ref={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<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 emptyvalidation— a function(value) => booleanthat returnstrueif the value is validvalidationMessage— the error message shown whenvalidationreturnsfalse
import { useRef } from "react";
import { Gantt, Editor, getEditorItems } from "@svar-ui/react-gantt";
function App() {
const api = useRef(null);
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={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<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.interceptmethod to disable opening the default editor by blocking theshow-editoraction (return false) - Add the Form tag, define tasks and taskTypes, and add the action handler function that triggers the
update-taskordelete-taskaction.
import { useState, useRef } 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 api = useRef(null);
let store;
const init = (apiInstance) => {
store = apiInstance.getState().tasks;
apiInstance.intercept("show-editor", data => {
setTask(store.byId(data.id));
return false;
});
};
const formAction = (ev) => {
const { action, data } = ev;
switch (action) {
case "close-form":
setTask(null);
break;
default:
api.current.exec(action, data); // "update-task", "delete-task" actions
break;
}
};
return (
<>
<Gantt
tasks={data.tasks}
links={data.links}
scales={data.scales}
ref={api}
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={api} 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: Editor: readonly