Механизм расширения интерфейса календаря в Flatpickr строится вокруг DOM-хуков и прямого управления элементами, которые генерирует библиотека. В отличие от тяжёлых UI-фреймворков, Flatpickr не предоставляет декларативной системы шаблонов, поэтому добавление произвольного контента реализуется через жизненный цикл экземпляра и модификацию DOM-узлов календаря.
Ключевая особенность подхода — работа с уже отрендеренными элементами через API событий и callback-функции.
После инициализации Flatpickr создаёт контейнер с классом
.flatpickr-calendar, внутри которого формируется:
Каждый день месяца представлен элементом .flatpickr-day,
который создаётся динамически при каждом рендере.
Именно этот слой становится точкой расширения для вставки пользовательского контента.
onDayCreate как основной механизм расширения ячеекНаиболее прямой способ добавить произвольный контент в ячейки
календаря — использование onDayCreate. Этот callback
вызывается при создании каждого DOM-элемента дня.
flatpickr("#calendar", {
onDayCreate: function(dObj, dStr, fp, dayElem) {
const date = dayElem.dateObj;
if (date.getDay() === 1) {
const badge = document.createElement("span");
badge.className = "custom-badge";
badge.textContent = "M";
dayElem.appendChild(badge);
}
}
});
В данном контексте dayElem — это уже готовый DOM-узел, в
который можно добавлять любые дочерние элементы:
Особенность: onDayCreate вызывается при
каждом рендере, включая смену месяца, поэтому логика должна быть
идемпотентной.
Распространённый сценарий — отображение событий внутри конкретных дат.
const events = {
"2026-06-03": ["meeting", "deploy"],
"2026-06-10": ["vacation"]
};
flatpickr("#calendar", {
onDayCreate: function(_, __, fp, dayElem) {
const iso = fp.formatDate(dayElem.dateObj, "Y-m-d");
if (events[iso]) {
const container = document.createElement("div");
container.className = "event-dots";
events[iso].forEach(() => {
const dot = document.createElement("span");
dot.className = "event-dot";
container.appendChild(dot);
});
dayElem.appendChild(container);
}
}
});
Такой подход превращает календарь в слой визуализации данных, где DOM становится носителем метаинформации.
onReady для модификации структуры календаряonReady вызывается один раз после первичной отрисовки.
Этот хук подходит для добавления глобальных элементов, не привязанных к
отдельным дням.
Примеры задач:
flatpickr("#calendar", {
onReady: function(selectedDates, dateStr, fp) {
const footer = document.createElement("div");
footer.className = "fp-footer";
footer.textContent = "Статус: синхронизировано";
fp.calendarContainer.appendChild(footer);
}
});
fp.calendarContainer — корневой DOM-узел календаря,
через который можно расширять структуру без вмешательства в внутреннюю
разметку.
Flatpickr не предоставляет официального шаблонизатора заголовка,
однако его можно модифицировать через prevMonthNav и
nextMonthNav, а также через прямой доступ к
.cur-month.
flatpickr("#calendar", {
onReady: function(_, __, fp) {
const title = fp.monthNav.querySelector(".cur-month");
const indicator = document.createElement("span");
indicator.className = "sync-indicator";
indicator.textContent = "●";
title.appendChild(indicator);
}
});
Такой подход используется для добавления:
При смене месяца Flatpickr полностью пересоздаёт DOM-дни. Это означает, что любые добавленные элементы должны восстанавливаться автоматически через хук.
Подход основан на хранении состояния вне DOM:
const notes = {
"2026-06-15": "Deadline",
"2026-06-20": "Review"
};
flatpickr("#calendar", {
onDayCreate: function(_, __, fp, dayElem) {
const key = fp.formatDate(dayElem.dateObj, "Y-m-d");
if (notes[key]) {
const note = document.createElement("div");
note.className = "day-note";
note.textContent = notes[key];
dayElem.appendChild(note);
}
}
});
DOM рассматривается как производное состояние от внешней модели данных.
hook-цепочек для сложной логикиFlatpickr поддерживает несколько событий, которые можно комбинировать:
onMonthChangeonYearChangeonValueUpdateonOpenonCloseКомбинация этих событий позволяет строить многоуровневую систему вставки контента.
flatpickr("#calendar", {
onMonthChange: function(selectedDates, dateStr, fp) {
fp.redraw();
},
onDayCreate: function(_, __, fp, dayElem) {
const date = dayElem.dateObj;
if (date.getDate() === 1) {
const label = document.createElement("span");
label.textContent = "Start";
label.className = "month-start-label";
dayElem.appendChild(label);
}
}
});
Иногда требуется не только вставка внутрь ячеек, но и создание параллельных слоёв интерфейса.
Flatpickr позволяет использовать wrap: true, что даёт
доступ к обёртке:
flatpickr("#wrapper", {
wrap: true,
onReady: function(_, __, fp) {
const overlay = document.createElement("div");
overlay.className = "calendar-overlay";
fp.calendarContainer.appendChild(overlay);
}
});
Overlay-слои применяются для:
Добавление произвольного контента тесно связано с ручным контролем обновления UI.
Метод redraw() используется для полной перегенерации
DOM:
fp.setDate("2026-06-10");
fp.redraw();
При использовании динамического контента важно учитывать:
Прямое вмешательство в DOM требует соблюдения ограничений:
.flatpickr-day между рендерамиПредпочтительный подход — добавление собственных классов и контейнеров:
dayElem.classList.add("has-custom-content");
Это позволяет отделить пользовательский слой от внутреннего механизма библиотеки.
Для сложных сценариев добавления контента используется обёртка над Flatpickr как плагин:
function customContentPlugin(fp) {
return {
onDayCreate(_, __, instance, dayElem) {
const marker = document.createElement("i");
marker.className = "plugin-marker";
dayElem.appendChild(marker);
}
};
}
flatpickr("#calendar", {
plugins: [customContentPlugin]
});
Такой подход масштабируется лучше, чем разрозненные хуки, поскольку инкапсулирует логику расширения.
Произвольный контент может включать интерактивные элементы:
dayElem.addEventListener("click", (e) => {
if (e.target.classList.contains("quick-action")) {
console.log("Action triggered");
}
});
Важно учитывать, что Flatpickr обрабатывает клики по дням, поэтому
вложенные элементы должны предотвращать конфликт событий при
необходимости через stopPropagation().
Добавление произвольного контента в Flatpickr опирается на три базовых слоя:
Эти механизмы формируют единый паттерн расширения, в котором DOM остаётся управляемым, а данные — внешними и независимыми от рендера.