Множественная инициализация на странице

Библиотека Flatpickr изначально проектировалась как легковесный и гибкий инструмент для работы с датами, где ключевой архитектурный принцип — независимость каждого экземпляра календаря. Это означает, что на одной странице может существовать любое количество инстансов, каждый из которых изолирован по состоянию, конфигурации и DOM-привязке. Такая модель особенно важна для динамических интерфейсов, форм с повторяющимися блоками и сложных SPA-приложений.


Базовый принцип множественной инициализации

Каждый вызов flatpickr() создаёт отдельный экземпляр, связанный с конкретным DOM-элементом. При этом библиотека не требует глобального регистра экземпляров и не использует централизованное состояние.

flatpickr("#date1");
flatpickr("#date2");
flatpickr("#date3");

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

Ключевая особенность заключается в том, что:

  • каждый инстанс имеет собственную конфигурацию;
  • события не пересекаются между экземплярами;
  • изменение одного календаря не влияет на другие;
  • DOM-структура каждого picker создаётся отдельно.

Массовая инициализация через выборку элементов

Чаще всего множественная инициализация выполняется через querySelectorAll, что позволяет обработать набор элементов одним вызовом логики.

document.querySelectorAll(".date-input").forEach((el) => {
  flatpickr(el, {
    dateFormat: "Y-m-d"
  });
});

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

Особенности поведения:

  • каждый элемент получает собственный календарь;
  • конфигурация может быть общей или динамической;
  • библиотека не требует хранения массива инстансов вручную (если не требуется дальнейшее управление).

Индивидуальная конфигурация для каждого экземпляра

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

document.querySelectorAll(".date-input").forEach((el) => {
  flatpickr(el, {
    dateFormat: el.dataset.format || "Y-m-d",
    minDate: el.dataset.min || null,
    maxDate: el.dataset.max || null
  });
});

Такой подход часто применяется в формах, где ограничения зависят от контекста:

  • диапазоны дат, заданные сервером;
  • локализация интерфейса;
  • ограничения бронирования;
  • пользовательские правила валидации.

Хранение ссылок на экземпляры

При необходимости управления уже созданными календарями (например, программное изменение даты или уничтожение инстанса) требуется сохранять ссылки на объекты.

const instances = [];

document.querySelectorAll(".date-input").forEach((el) => {
  const instance = flatpickr(el, {
    enableTime: true
  });

  instances.push(instance);
});

Каждый экземпляр предоставляет API:

  • setDate()
  • clear()
  • destroy()
  • open()
  • close()

Это позволяет централизованно управлять всеми календарями.


Динамическое добавление элементов

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

function initDatePicker(el) {
  return flatpickr(el, {
    dateFormat: "Y-m-d"
  });
}

const container = document.querySelector("#container");

function addField() {
  const input = document.createElement("input");
  input.className = "date-input";
  container.appendChild(input);

  initDatePicker(input);
}

Каждый новый input получает собственный экземпляр без повторной инициализации остальных элементов.


Повторная инициализация и защита от дублирования

При повторном запуске инициализации на одном и том же элементе может возникнуть проблема создания нескольких экземпляров. Flatpickr хранит ссылку на инстанс внутри DOM-узла, но при неправильной логике повторная инициализация возможна.

Типичный способ защиты:

document.querySelectorAll(".date-input").forEach((el) => {
  if (el._flatpickr) return;

  flatpickr(el);
});

Свойство _flatpickr содержит текущий экземпляр, если он уже был создан.


Использование разных конфигураций на одной странице

Множественная инициализация особенно полезна при комбинировании различных режимов работы календаря.

flatpickr("#start-date", {
  dateFormat: "Y-m-d"
});

flatpickr("#end-date", {
  enableTime: true,
  dateFormat: "Y-m-d H:i"
});

flatpickr("#birthday", {
  maxDate: "today",
  disableMobile: true
});

Каждый календарь работает в своём режиме, несмотря на одинаковую библиотеку.


Изоляция состояния экземпляров

Внутренне каждый инстанс хранит:

  • выбранную дату;
  • текущее состояние UI;
  • настройки форматирования;
  • локализацию;
  • обработчики событий.

Это означает, что:

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

События в множественных инстансах

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

document.querySelectorAll(".date-input").forEach((el) => {
  flatpickr(el, {
    onChange: (selectedDates, dateStr) => {
      console.log(el.id, dateStr);
    }
  });
});

При этом важно учитывать, что callback получает контекст конкретного инстанса, а не глобального состояния.


Производительность при большом количестве экземпляров

При большом числе календарей на странице (десятки или сотни) основная нагрузка возникает не на JavaScript-логике, а на DOM:

  • генерация календарных попапов;
  • обработка событий hover/click;
  • рендеринг сетки дат.

Практическая особенность Flatpickr:

  • минимальный overhead на каждый экземпляр;
  • отсутствие глобального state manager;
  • ленивое отображение календаря (UI создаётся по необходимости).

Удаление экземпляров при переработке интерфейса

При удалении элементов из DOM желательно корректно уничтожать связанные инстансы.

instances.forEach((instance) => {
  instance.destroy();
});

После вызова destroy():

  • удаляется DOM календаря;
  • снимаются обработчики событий;
  • очищаются внутренние ссылки.

Работа в табличных и повторяющихся структурах

Множественная инициализация часто используется в:

  • таблицах с редактируемыми строками;
  • формах бронирования;
  • CRM-интерфейсах;
  • админ-панелях.

Пример:

document.querySelectorAll("table .date-cell input").forEach((el) => {
  flatpickr(el, {
    allowInput: true
  });
});

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


Комбинация с делегированием событий

Хотя Flatpickr создаёт независимые инстансы, иногда используется делегирование для упрощения логики инициализации.

document.addEventListener("focusin", (e) => {
  if (e.target.matches(".date-input") && !e.target._flatpickr) {
    flatpickr(e.target);
  }
});

Такой подход полезен для динамически генерируемого DOM без необходимости повторной ручной инициализации.


Итоговая архитектурная модель множественной инициализации

Поведение Flatpickr при множественной инициализации можно свести к следующим принципам:

  • каждый DOM-элемент = отдельный независимый экземпляр;
  • конфигурация не наследуется автоматически;
  • состояние полностью изолировано;
  • управление осуществляется через ссылки на инстансы;
  • повторная инициализация требует контроля через _flatpickr.

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