Перейти к основному содержимому

Загрузка данных

dhtmlxGantt может принимать данные в двух форматах:

Чтобы загрузить данные в диаграмму Ганта, используйте метод [parse] или [load].

gantt.init("gantt_here");
gantt.load("tasks.json");

Связанный пример: Базовая инициализация

заметка

Если вы передадите неверные данные в Gantt, его древовидная структура станет циклической, что вызывает cyclic reference error.

Загрузка из объекта

Чтобы загрузить данные из объекта, используйте метод [parse]:

Загрузка из встроенного источника данных
const data = {
tasks: [
{ id: 1, text: "Project #1", start_date: "01-12-2025", duration: 18 },
{ id: 2, text: "Task #1", start_date: "02-12-2025", duration: 8, parent: 1 },
{ id: 3, text: "Task #2", start_date: "11-12-2025", duration: 8, parent: 1 }
]
};

gantt.init("gantt_here");
gantt.parse(data); /*!*/

Связанный пример: Базовая инициализация

заметка

Если ваши объекты данных содержат как значения start_date, так и end_date и даты содержат только часть даты (т.е. 01-12-2025, без 00:00) — может потребоваться дополнительная настройка. Обязательно ознакомьтесь со статьей Task end date display & Inclusive end dates.

Загрузка с сервера

Клиентская сторона

Чтобы загрузить данные с сервера, используйте метод [load]:

gantt.html
gantt.init("gantt_here");
gantt.load("data.json"); /*!*/

Метод load отправит AJAX-запрос на указанный URL и ожидает ответ с данными в одном из поддерживаемых форматов (guides/supported-data-formats.md). Например:

data.json
{
"tasks": [
{ "id": 1, "text": "Project #1", "start_date": "01-12-2025", "duration": 18 },
{ "id": 2, "text": "Task #1", "start_date": "02-12-2025", "duration": 8,"parent": 1 },
{ "id": 3, "text": "Task #2", "start_date": "11-12-2025", "duration": 8, "parent": 1 }
],
"links": [
{ "id": 1, "source": 1, "target": 2, "type": "1" },
{ "id": 2, "source": 2, "target": 3, "type": "0" }
]
}

Формат задаётся вторым аргументом метода: "json", "xml" или "oldxml".

gantt.load("data.xml", "xml");

Серверная сторона

На сервере вы можете иметь либо статический файл с данными, либо скрипт, который будет собирать данные из источника данных и записывать их в ответ. Реализация на стороне сервера зависит от выбранного вами фреймворка.

заметка

Смотрите подробные инструкции и примеры кода для различных платформ в статье .

Например, в случае Node.js следует добавить маршрут сервера для URL, по которому Gantt будет отправлять AJAX-запрос за данными.

gantt.load("/data"); 

Он сгенерирует соответствующий ответ в формате JSON.

app.get("/data", (req, res) => {
db.query("SELECT * FROM gantt_tasks", (err, tasks) => {
if (err) console.log(err);

db.query("SELECT * FROM gantt_links", (err, links) => {
if (err) console.log(err);

tasks.forEach((task) => {
task.start_date = task.start_date.format("YYYY-MM-DD");
task.open = true;
});

res.send({ tasks, links });
});
});
});
заметка

См. все поддерживаемые форматы данных в статье Supported Data Formats.

Загрузка дат задач

Установка графика задачи

Существует три способа задать график задачи в наборе данных:

  • start_date + duration
  • start_date + end_date
  • duration + end_date

Свойство, которое не указано, будет вычислено на основе заданных в объекте данных.

Связанный пример: Backward planning

Глобальная концепция: у end_date выше приоритет над параметром duration. Если в задаче указаны три параметра, Gantt проигнорирует параметр duration и задача загрузится с другим значением длительности. Например:

{
"id": "20", "text": "Project #2",
"start_date": "01-12-2025",
"duration": 3,
"end_date": "05-12-2025",
}

// задача выше будет загружена с длительностью, вычисленной в соответствии
// с указанными 'start_date' и 'end_date'
{
"id": "20", "text": "Project #2",
"start_date": "01-12-2025",
"duration": 4,
"end_date": "05-12-2025",
}

Загрузка дат в ISO-формате

С версии 9.1.3 Gantt автоматически распознаёт и парсит даты ISO 8601. Конфигурация не требуется.

Поддерживаемые форматы:

  • 2026-01-06 - только дата
  • 2026-01-06T10:30:00 - дата и время
  • 2026-01-06T10:30:00.000 - дата и время с миллисекундами
  • 2026-01-06T10:30:00.000Z - UTC
  • 2026-01-06T10:30:00+02:00 - с часовым поясом
gantt.parse({
tasks: [
{ id: 2, text: "Task #1", start_date: "2026-01-06T10:30:00Z", duration: 3 }
],
links: []
});
ISO-даты распознаются автоматически — отключения шаблонов не требуются

Когда на входе обнаружены ISO-даты, они автоматически сериализуются обратно в ISO-строки, когда передаются в DataProcessor. Строки с только датой (например, "2026-01-06") сериализуются обратно как строки даты, сохраняя исходный формат. Если вход содержит смесь строк только даты и полных дат и времени, все даты сериализуются как полные дату и время.

заметка

Строки только даты (например, "2026-01-06") парсятся как локальная полночь, когда server_utc установлен в false (значение по умолчанию).

заметка

Если вы явно переопределите gantt.templates.parse_date или gantt.templates.format_date, ваши функции получают приоритет над автоматическим обнаружением ISO и автоматической сериализацией.

Gantt v9.1.2 и ранее

В версиях до v9.1.3 ISO-даты не распознавались автоматически. Если вы используете более старую версию, вам нужно переопределить шаблоны parse_date и format_date, чтобы обрабатывать ISO-строки:

gantt.templates.parse_date = (date) => {
return new Date(date);
};

gantt.templates.format_date = (date) => {
return date.toISOString();
};

В версиях 9.1.3+ эти шаблоны всё ещё используются как запасной вариант для не-ISO строк дат. См. gantt.date.parseDate() для полного конвейера разбора.

Динамическое изменение формата даты

Если вам нужно динамически изменить date format, необходимо изменить шаблон parse_date следующим образом:

const cfg = gantt.config;
const strToDate = gantt.date.str_to_date(cfg.date_format, cfg.server_utc);

gantt.templates.parse_date = (date) => {
return strToDate(date);
};

Отображение конечной даты задачи и Инклюзивная конечная дата

Этот раздел ответит на вопрос: «Как правильно сохранить и отобразить конечную дату задачи?».

Во-первых, рассмотрим два возможных сценария, с которыми вы можете столкнуться при работе с датами задач:

Сценарий 1

  • Когда продолжительность задачи измеряется целыми днями (duration_unit="day")
  • Когда объекты данных задачи содержат начальные и конечные даты в формате "%Y-%m-%d" или "%d-%m-%Y" (то есть без части часа)

Из-за нюансов того, как dhtmlxGantt интерпретирует и сохраняет конечные даты задач, результат может оказаться неожиданным.

Посмотрите следующий пример:

gantt.parse({
tasks: [
{
id: 1,
text: "Task 1",
start_date: "22-12-2025",
end_date: "22-12-2025"
}
],
links: []
});

console.log(gantt.getTask(1).end_date);
// 22 December 2025 00:00:00

console.log(gantt.getTask(1).duration);
// 0

В этом примере и начальная, и конечная даты относятся к одной точке времени, и длительность задачи будет равна 0.

Сценарий 2

  • Когда конечная дата задачи отображается в гриде
  • И формат конечной даты не содержит части часа и минут
gantt.config.columns = [
{ name: "text", label: "Name", tree: true, width: 200, resize: true },
{ name: "duration", label: "Duration", width: 80, align: "center", resize: true },
{ name: "start_date", label: "Start", width: 80, align: "center", resize: true },
{ name: "end_date", label: "Finish", width: 80, align: "center", resize: true }
];

gantt.init("gantt_here");

gantt.parse({
tasks: [
{
id: 1,
text: "Task 1",
start_date: "22-12-2025",
end_date: "23-12-2025"
}
],
links: []
});

В этом примере дата окончания (end_date) указана как 23 декабря, тогда как задача заканчивается в конце 22 декабря.

end_date

Далее мы поясним, как Gantt хранит конечные даты.

Как Gantt хранит конечные даты

Даже если не задавать часть часа и минуты для даты задачи (duration_unit = "day"), dhtmlxGantt всегда сохраняет её как JS Date, который имеет часть часов, минут, секунд и миллисекунд на клиентской стороне.

Текущий формат конечных дат следующий:

  • секунды и миллисекунды даты всегда равны 0; Gantt не поддерживает единицы менее минуты
  • конец даты задачи задаётся как начало дня ("day-hour-minute") следующего за последним рабочим днём ("day-hour-minute"). То есть:
    • задача, которая начинается 22 декабря и длится 1 день, будет иметь начало и конец: "22-12-2025 00:00:00 - 23-12-2025 00:00:00". Конечная дата совпадает с началом следующего дня после 22 декабря
    • задача, которая начинается 22 декабря в 13:00 и длится 1 час, будет иметь начало и конец: "22-12-2025 13:00:00 - 22-12-2025 14:00:00". Конечная дата совпадает с началом следующего часа

Если показывать конечную дату на экране без указания части часа и минут, результат может быть введён в заблуждение. В примере из сценария 2 начальная и конечная даты будут выглядеть как "22-12-2025 - 23-12-2025". Это может заставить подумать, что задача длится не 1 день, а 2 (с 22 по 23 декабря).

Это поведение по умолчанию и может запутать, но есть возможность исправить его через конфигурацию. В следующей части мы покажем несколько способов решения.

Как изменить поведение по умолчанию

1) Первое, что вы не должны делать, — изменять фактические даты задач, которые хранятся в Gantt.

Также можно изменить даты задач, которые загружаются в диаграмму Gantt, например, задать окончания как 22-12-2025 23:59:59. Но лучше так не делать, потому что такие решения могут конфликтовать с вычислением длительности задач и автоматическим планированием.

Вместо этого рекомендуем использовать следующие методы:

2a) Чтобы изменить формат конечных дат задач в диаграмме Gantt (то есть включать конечную дату в длительность задач), вы можете переопределить шаблон task_end_date.

Возьмём задачу, которая начинается 22 декабря 2025 года и длится один день, и рассмотрим, как шаблон может изменить конечную дату.

По умолчанию конечная дата этой задачи должна отображаться как 23 декабря 2025 года (23-12-2025 00:00:00):

task_end_date_template_default

Но если вы примените шаблоны task_end_date и grid_date_format, та же задача будет завершена 22 декабря 2025 года:

task_end_date_template

Код выглядит так:

// Переопределение шаблона
gantt.templates.task_end_date = (date) => {
return gantt.templates.task_date(new Date(date.valueOf() - 1));
};

const gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");

gantt.templates.grid_date_format = (date, column) => {
if (column === "end_date") {
return gridDateToStr(new Date(date.valueOf() - 1));
} else {
return gridDateToStr(date);
}
};

gantt.init("gantt_here");

Такой подход позволяет изменить дату окончания задачи, отображаемую в гриде, заголовке лайтбокса и в любых других местах, где нужно показывать конечную дату.

Если вы используете format for inclusive end dates для задач и хотите корректной работы с inline editing в гриде, вам нужно создать специальный редактор для редактирования инклюзивных конечных дат задач, например:

// Inclusive editor for end dates
// Use the default editor, but override the set_value/get_value methods
const dateEditor = gantt.config.editor_types.date;

gantt.config.editor_types.end_date = gantt.mixin(
{
set_value: (value, id, column, node) => {
const correctedValue = gantt.date.add(value, -1, "day");
return dateEditor.set_value.apply(this, [correctedValue, id, column, node]);
},
get_value: (id, column, node) => {
const selectedValue = dateEditor.get_value.apply(this, [id, column, node]);
return gantt.date.add(selectedValue, 1, "day");
},
},
dateEditor
);

const textEditor = { type: "text", map_to: "text" };
const startDateEditor = { type: "date", map_to: "start_date" };
const endDateEditor = { type: "end_date", map_to: "end_date" };
const durationEditor = { type: "number", map_to: "duration", min: 0, max: 100 };

gantt.config.columns = [
{ name: "text", label: "Name", tree: true, width: 200, editor: textEditor, resize: true },
{ name: "duration", label: "Duration", width: 80, align: "center", editor: durationEditor, resize: true },
{ name: "start_date", label: "Start", width: 140, align: "center", editor: startDateEditor, resize: true },
{ name: "end_date", label: "Finish", width: 140, align: "center", editor: endDateEditor, resize: true }
];

// Change lightbox and grid templates to display dates of tasks in an inclusive format
gantt.templates.task_end_date = (date) => {
return gantt.templates.task_date(new Date(date.valueOf() - 1));
};

const gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");

gantt.templates.grid_date_format = (date, column) => {
if (column === "end_date") {
return gridDateToStr(new Date(date.valueOf() - 1));
} else {
return gridDateToStr(date);
}
};

2b) Если другие части приложения требуют хранения конечных дат в формате "inclusive" — т.е. задача, начинающаяся 22 декабря 2025 года и длительная 1 день, должна храниться как start_date: "22-12-2025", end_date: "22-12-2025" — вам необходимо реализовать дополнительную обработку конечных дат, а именно:

  • прибавлять один день к конечным датам перед загрузкой данных в Gantt
  • вычитать один день из конечных дат перед сохранением изменений, полученных из Gantt, обратно в хранилище данных

Свойства данных

Источник данных для диаграммы Гantt — это объект, который хранит 2 типа информации:

  • tasks - элементы задач.
  • links - элементы зависимостей.

Свойства объекта задачи

заметка

Полный список свойств объекта задачи приведён в статье Свойства задачи.

Формат даты по умолчанию для данных JSON и XML — "%d-%m-%Y %H:%i" (см. спецификация формата даты).

Чтобы изменить его, используйте настройку date_format.

gantt.config.date_format="%Y-%m-%d";
gantt.init("gantt_here");

После загрузки в Gantt свойства start_date и end_date будет разобраны как тип Date.

Форматы дат, не поддерживаемые конфигурацией [date_format], можно разобрать вручную через шаблон parse_date.

заметка

Полный перечень свойств объекта ссылки приведён в статье Свойства ссылки.

Пользовательские свойства

Вы не ограничены обязательными свойствами, указанными выше, и можете добавлять любые пользовательские свойства к элементам данных. Дополнительные свойства данных будут разобраны как строки и загружены на клиентскую сторону, где вы сможете использовать их по мере необходимости.

См. примеры данных с пользовательскими свойствами здесь.

Структура базы данных

Если вы используете базу данных, рекомендуется иметь 2 отдельные таблицы для хранения данных: одну для задач и одну для связей.

tutorial_db_tables

Структура стандартной базы данных для загрузки задач и связей в диаграмму Гantt:

  • gantt_tasks таблица - содержит задачи диаграммы Ганта
    • id - (string,number) идентификатор события.
    • start_date - (Date) дата, когда задача должна начаться.
    • text - (string) описание задачи.
    • progress - (number) число от 0 до 1, показывающее, какой процент задачи закончен.
    • duration - (number) длительность задачи в единицах текущей временной шкалы.
    • parent - (number) идентификатор родительской задачи.
    • type - (string) необязателен, тип задачи.
    • readonly - (boolean) необязателен, можно пометить задачу как readonly.
    • editable - (boolean) необязателен, можно пометить задачу как editable.
  • gantt_links таблица - задаёт связи зависимостей диаграммы Гantt
    • id - (string) идентификатор события.
    • source - (number) идентификатор исходной задачи.
    • target - (number) идентификатор целевой задачи.
    • type - (string) тип зависимости:
      • 0 - 'finish_to_start'
      • 1 - 'start_to_start'
      • 2 - 'finish_to_finish'
      • 3 - 'start_to_finish'
    • lag - (number) необязателен, задержка задачи.
    • readonly - (boolean) необязателен, можно пометить связь как readonly.
    • editable - (boolean) необязателен, можно пометить связь как editable.

Используйте следующий SQL-запрос для создания базы данных с двумя упомянутыми таблицами:

CREATE TABLE `gantt_links` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`source` int(11) NOT NULL,
`target` int(11) NOT NULL,
`type` varchar(1) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `gantt_tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
`start_date` datetime NOT NULL,
`duration` int(11) NOT NULL,
`progress` float NOT NULL,
`sortorder` int(11) NOT NULL,
`parent` int(11) NOT NULL,
PRIMARY KEY (`id`)
)

Потоки событий

Методы загрузки имеют следующий поток событий:

gantt.parse():

gantt.load():

gantt.refreshData():

gantt.render():

Need help?
Got a question about the documentation? Reach out to our technical support team for help and guidance. For custom component solutions, visit the Services page.