Порядок вызова событий

Инициализация экземпляра Flatpickr запускает первичный цикл событий, в котором формируется базовое состояние календаря, подготавливается DOM-разметка и устанавливаются внутренние ссылки на элементы управления. На этом этапе ключевую роль играет событие onReady, фиксирующее момент полной готовности виджета к взаимодействию. Оно всегда происходит после построения календаря, но до первого пользовательского взаимодействия и до большинства событий, связанных с выбором дат.

После вызова flatpickr(element, options) библиотека проходит несколько внутренних стадий, каждая из которых может сопровождаться событиями:

  1. Создание экземпляра и парсинг конфигурации
  2. Построение DOM календаря
  3. Привязка обработчиков событий
  4. Первичная отрисовка текущего состояния
  5. Срабатывание onReady

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

Открытие календаря и событие onOpen

При первом взаимодействии пользователя или программном вызове instance.open() запускается последовательность открытия:

  • Проверка состояния экземпляра (disabled, inline, readonly)
  • Расчёт позиции попапа
  • Применение анимации открытия
  • Отрисовка актуального месяца/даты

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

Выбор даты и основной поток событий

Центральная часть жизненного цикла Flatpickr связана с выбором даты. При клике по дню или программном вызове setDate() формируется последовательность:

  • Проверка валидности даты
  • Обновление внутреннего состояния
  • Пересчёт выделения дней
  • Обновление инпута (если включён режим связки с input)

Здесь возникает ключевой порядок событий:

onValueUpdate → onChange

onValueUpdate

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

Характерная особенность — оно вызывается чаще, чем onChange, и может срабатывать даже при промежуточных изменениях, например при выборе диапазона дат.

onChange

onChange вызывается после того, как изменение считается завершённым и стабилизированным. В отличие от onValueUpdate, оно ориентировано на финальный результат взаимодействия пользователя.

Типичная последовательность при выборе одной даты:

  1. Пользователь кликает по дню
  2. Обновляется внутреннее состояние
  3. Срабатывает onValueUpdate
  4. Обновляется значение input
  5. Срабатывает onChange

При выборе диапазона дат возможна многократная активация onValueUpdate до финального onChange.

Навигация по месяцам и годам

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

onMonthChange

Срабатывает при изменении месяца, независимо от причины:

  • нажатие стрелок навигации
  • программный вызов changeMonth
  • автоматическое переключение при выходе за пределы месяца

Порядок внутри операции:

  1. Обновление текущего месяца
  2. Перерисовка календарной сетки
  3. Срабатывание onMonthChange

onYearChange

Аналогично, но для изменения года:

  1. Изменение внутреннего значения года
  2. Перестройка представления месяцев
  3. Срабатывание onYearChange

Важно, что при смене месяца и года одновременно (например, декабрь → январь следующего года) события могут следовать последовательно:

  • сначала onMonthChange
  • затем onYearChange

или наоборот, в зависимости от механизма перехода, но всегда после завершения перерасчёта UI.

Создание и перерисовка дней

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

onDayCreate

Срабатывает при создании DOM-элемента конкретного дня. Последовательность:

  1. Генерация структуры месяца
  2. Итерация по дням
  3. Создание DOM-узла дня
  4. Вызов onDayCreate для каждого элемента

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

Особенность заключается в том, что onDayCreate может вызываться многократно при:

  • смене месяца
  • смене года
  • изменении диапазона дат
  • обновлении min/max ограничений

Закрытие календаря и onClose

Закрытие календаря формирует завершающий поток взаимодействия:

  • проверка состояния выбора
  • запуск анимации закрытия
  • скрытие pop-up
  • очистка временных состояний UI

Событие onClose срабатывает после начала процесса закрытия, когда интерфейс уже считается неактивным, но DOM ещё может быть доступен для операций.

Типичная последовательность при закрытии:

  1. Пользователь завершает выбор или кликает вне календаря
  2. Инициируется закрытие
  3. Срабатывает onClose
  4. Завершается анимация
  5. Попап скрывается

Полная типовая цепочка событий при выборе даты

При стандартном сценарии (одна дата, без диапазона) последовательность выглядит следующим образом:

  1. onReady — при инициализации
  2. onOpen — при открытии
  3. onValueUpdate — при выборе даты
  4. onChange — фиксация изменения
  5. onClose — завершение взаимодействия

Дополнительно могут быть вставлены:

  • onMonthChange — при навигации
  • onYearChange — при смене года
  • onDayCreate — при рендере сетки

Особенности порядка вызовов при диапазонах дат

Режим range существенно усложняет последовательность событий. При выборе начальной и конечной даты:

  • первый клик инициирует onValueUpdate без onChange
  • второй клик завершает диапазон и вызывает onChange
  • при движении мыши возможны промежуточные пересчёты выделения

Внутренний поток становится итеративным:

  • изменение состояния → onValueUpdate
  • повторное изменение → onValueUpdate
  • финализация → onChange

Программное управление и изменение порядка

При использовании API (setDate, jumpToDate, clear) порядок событий может отличаться от пользовательского сценария.

Например, при setDate:

  1. Обновление значения
  2. Пересчёт состояния
  3. onValueUpdate
  4. Условный onChange (если не подавлен опцией)

При этом onOpen и onClose не всегда вызываются при программных изменениях.

Влияние конфигурации на последовательность

Некоторые параметры изменяют порядок или частоту событий:

  • enableTime добавляет дополнительные стадии пересчёта значения
  • inline убирает onOpen и onClose как пользовательские события
  • mode: "multiple" увеличивает количество onValueUpdate
  • allowInput добавляет внешние триггеры для onChange

Приоритеты событий и внутренний цикл

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

Приоритет условно можно представить так:

  1. Внутреннее состояние
  2. Перерисовка DOM
  3. onDayCreate (если рендер)
  4. onValueUpdate
  5. onChange
  6. UI-события открытия/закрытия (onOpen, onClose)

Взаимодействие событий между собой

События Flatpickr не являются изолированными. Например:

  • onMonthChange всегда предшествует onDayCreate
  • onValueUpdate может вызываться несколько раз до onChange
  • onOpen может сопровождаться последующим onMonthChange при автоматической корректировке даты
  • onYearChange часто сопровождает полную переразметку календаря

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

Программная синхронизация логики через события

При построении сложной логики взаимодействия с календарём используется комбинирование событий:

  • onReady для инициализации состояния
  • onOpen для загрузки внешних данных
  • onDayCreate для модификации UI каждого дня
  • onValueUpdate для реактивного отслеживания изменений
  • onChange для фиксации результата
  • onClose для очистки состояния

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