Skip to main content
The Editor component renders a side panel (or modal) that lets users view and edit task properties. It connects to the Gantt chart through the shared api object.

Basic setup

1

Import the components

Import both Gantt and Editor from the package.
import { Gantt, Editor } from "@svar-ui/svelte-gantt";
2

Create a shared api reference

Declare a reactive api variable and pass it to both components using bind:this on Gantt or the init callback.
<script>
  import { Gantt, Editor } from "@svar-ui/svelte-gantt";
  import { getData } from "./data";

  const data = getData();
  let api = $state();

  function init(ganttApi) {
    api = ganttApi;
    // open the editor automatically after a task is added
    api.on("add-task", ({ id }) => {
      api.exec("show-editor", { id });
    });
  }
</script>

<Gantt
  {init}
  tasks={data.tasks}
  links={data.links}
  scales={data.scales}
/>
<Editor {api} />
Editor must receive the same api instance as Gantt. Using bind:this={api} on Gantt is the simplest way to achieve this.

Editor props

api
IApi
The Gantt API object. Connects the editor to the chart so it can read and write task data.
items
TEditorItem[]
Array of editor field descriptors. Overrides the default set of fields rendered in the panel.
placement
'sidebar' | 'modal'
default:"sidebar"
Controls where the editor appears. Use "modal" to open it as a centred dialog.
autoSave
boolean
default:"true"
When true, changes are saved automatically as the user edits fields. Set to false to require an explicit save action.
topBar
boolean | object
default:"true"
Show or hide the title bar at the top of the editor. Pass false to remove it entirely.
bottomBar
object
Configuration for the button bar at the bottom of the editor. Accepts an items array of toolbar-style button descriptors.

Default editor items

The defaultEditorItems array defines the built-in fields shown in the editor. You can import it directly or call getEditorItems() to get a fresh copy that has task-type options populated from the current config.
<script>
  import { defaultEditorItems, getEditorItems } from "@svar-ui/svelte-gantt";

  // static reference
  console.log(defaultEditorItems);

  // copy with populated task-type options
  const items = getEditorItems();
</script>
The default fields are:
KeyComponentNotes
texttextTask name
detailstextareaDescription
typeselectTask type; hidden for segment tasks
startdateStart date; hidden for summary tasks
enddateEnd date; hidden for summary and milestone tasks
durationcounterDuration; hidden for summary and milestone tasks
progresssliderProgress percentage; hidden for milestones
linkslinksDependency links; hidden for segment tasks

Editor item fields

Each item in the items array is an object with the following properties:
comp
string
required
The control type. Built-in values: "text", "textarea", "date", "counter", "slider", "combo", "select", "multiselect", "radio", "checkbox", "links", "twostate".
key
string
required
The task property this field reads from and writes to.
label
string
Display label shown above the field.
labelTemplate
(value: any) => string
Function that returns a dynamic label based on the current field value.
config
Record<string, any>
Control-specific configuration options (e.g. { format: "%d-%m-%Y" } for date fields, { min: 1, max: 100 } for sliders).
isHidden
(task: Partial<ITask>) => boolean
Function that returns true to hide the field for a particular task.
isDisabled
(task: Partial<ITask>, state: IData) => boolean
Function that returns true to disable the field for a particular task and state.

Customising the field list

Use getEditorItems() to start from the defaults, then filter, reorder, or extend the array:
<script>
  import { Gantt, Editor, getEditorItems } from "@svar-ui/svelte-gantt";
  import { getData } from "./data";

  const data = getData();
  let api = $state();

  // select a specific subset of fields in a custom order
  const keys = ["text", "type", "start", "end", "duration", "progress", "details"];
  const defaultEditorItems = getEditorItems();
  const items = keys.map(key => ({
    ...defaultEditorItems.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" },
    ],
  };
</script>

<Gantt bind:this={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<Editor
  {api}
  {items}
  {bottomBar}
  topBar={false}
  placement="modal"
  autoSave={false}
/>

Custom controls

You can register your own Svelte components as editor controls with registerEditorItem. The registered name is then used as the comp value in an item descriptor.
<script>
  import {
    Gantt,
    Editor,
    registerEditorItem,
    getEditorItems,
    defaultTaskTypes,
  } from "@svar-ui/svelte-gantt";
  import { RadioButtonGroup } from "@svar-ui/svelte-core";
  import UsersCustomCombo from "./UsersCustomCombo.svelte";
  import { getData, users } from "./data";

  // register custom controls once, before rendering
  registerEditorItem("radio", RadioButtonGroup);
  registerEditorItem("custom-combo", UsersCustomCombo);

  const defaultEditorItems = getEditorItems();
  const items = defaultEditorItems.map(item => ({ ...item }));

  // replace the default type selector with a radio group
  items.splice(
    defaultEditorItems.findIndex(d => d.key === "type"),
    1,
    {
      key: "type",
      comp: "radio",
      label: "Type",
      options: defaultTaskTypes.map(o => ({ ...o, value: o.id })),
      config: { type: "inline" },
    },
    {
      key: "assigned",
      comp: "custom-combo",
      label: "Assigned",
      options: users,
    }
  );

  const data = getData();
  let api = $state();
</script>

<Gantt bind:this={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<Editor {api} {items} />
Call registerEditorItem once at module level, before the component tree is rendered, to avoid re-registration on each render.

Field validation

Add required to make a field mandatory, or provide a validation function and an optional validationMessage for custom rules:
<script>
  import { Gantt, Editor, getEditorItems } from "@svar-ui/svelte-gantt";
  import { getData } from "./data";

  const data = getData();
  let api = $state();

  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",
    }),
  }));
</script>

<Gantt bind:this={api} tasks={data.tasks} links={data.links} scales={data.scales} />
<Editor {api} {items} autoSave={false} />
Validation only runs when autoSave is false. With autoSave={true} (the default) each keystroke is saved immediately and validation is not triggered.

Readonly mode

To open the editor in a non-editable view, pass readonly to the Gantt component. You can also selectively disable individual fields using the isDisabled callback on each item:
<script>
  import { Gantt, Editor } from "@svar-ui/svelte-gantt";
  import { getData } from "./data";

  const data = getData();
  let api = $state();
</script>

<!-- entire gantt in readonly mode -->
<Gantt
  bind:this={api}
  readonly
  tasks={data.tasks}
  links={data.links}
  scales={data.scales}
/>
<Editor {api} />

Build docs developers (and LLMs) love