Интеграция с формами

Интеграция Pikaday с формами в веб-приложениях строится вокруг стандартного HTML-элемента input, значение которого синхронизируется с выбранной датой. Библиотека не заменяет форму, а расширяет её поведение, добавляя удобный визуальный выбор даты без нарушения привычного механизма отправки данных.

Базовый сценарий предполагает привязку календаря к текстовому полю:

const input = document.querySelector('#date');

const picker = new Pikaday({
    field: input,
    format: 'YYYY-MM-DD'
});

В этом режиме Pikaday автоматически записывает выбранную дату в value поля ввода. Форма при этом остаётся полностью стандартной и отправляется как обычный HTML.


Синхронизация формата даты и значения input

Одной из ключевых проблем при работе с датами в формах является единообразие формата. Pikaday использует форматирование через встроенную библиотеку Moment.js (или собственный форматтер в облегчённых сборках), что позволяет задавать единый стандарт представления даты.

const picker = new Pikaday({
    field: document.getElementById('birthdate'),
    format: 'DD.MM.YYYY'
});

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

Часто используется разделение отображаемого и передаваемого формата:

const picker = new Pikaday({
    field: document.querySelector('#date'),
    toString(date) {
        return date.toISOString().split('T')[0];
    },
    parse(dateString) {
        return new Date(dateString);
    }
});

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


Поведение при отправке формы

Pikaday не вмешивается в процесс отправки формы. Значение input.value остаётся единственным источником данных. Это делает библиотеку совместимой с серверным рендерингом и классическими HTML-формами.

<form id="bookingForm">
    <input type="text" id="checkin" name="checkin">
    <button type="submit">Отправить</button>
</form>
const picker = new Pikaday({
    field: document.getElementById('checkin'),
    format: 'YYYY-MM-DD'
});

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


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

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

<form id="form">
    <input type="text" id="visibleDate">
    <input type="hidden" name="date" id="hiddenDate">
</form>
const visible = document.getElementById('visibleDate');
const hidden = document.getElementById('hiddenDate');

const picker = new Pikaday({
    field: visible,
    format: 'DD.MM.YYYY',
    onSelect(date) {
        hidden.value = date.toISOString().split('T')[0];
    }
});

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


Валидация дат на уровне формы

Интеграция с формами часто требует контроля допустимых диапазонов дат. Pikaday предоставляет ограничения через параметры minDate и maxDate, что позволяет блокировать некорректный ввод ещё до отправки формы.

const picker = new Pikaday({
    field: document.getElementById('date'),
    minDate: new Date(2024, 0, 1),
    maxDate: new Date(2026, 11, 31)
});

Дополнительно можно синхронизировать валидацию с HTML5-атрибутами:

input.setAttribute('min', '2024-01-01');
input.setAttribute('max', '2026-12-31');

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


Связанные поля: диапазоны дат

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

<form>
    <input type="text" id="startDate" name="start">
    <input type="text" id="endDate" name="end">
</form>
const startInput = document.getElementById('startDate');
const endInput = document.getElementById('endDate');

const startPicker = new Pikaday({
    field: startInput,
    onSelect(date) {
        endPicker.setMinDate(date);
    }
});

const endPicker = new Pikaday({
    field: endInput,
    onSelect(date) {
        startPicker.setMaxDate(date);
    }
});

Связь календарей через setMinDate и setMaxDate предотвращает выбор некорректных диапазонов и снижает необходимость дополнительной серверной проверки.


Очистка и сброс значений формы

Формы часто требуют возможность сброса выбранной даты. Pikaday не блокирует очистку input.value, поэтому управление выполняется напрямую:

document.getElementById('reset').addEventListener('click', () => {
    input.value = '';
    picker.setDate(null);
});

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


Работа с disabled и readonly состояниями

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

input.readOnly = true;

Для полного запрета выбора даты используется дополнительная логика:

if (!input.readOnly && !input.disabled) {
    picker.show();
}

Это предотвращает открытие календаря в случаях, когда форма находится в защищённом состоянии (например, просмотр без редактирования).


Автозаполнение и предустановленные значения

При редактировании форм часто требуется инициализация календаря существующим значением.

const input = document.getElementById('date');

input.value = '2026-01-15';

const picker = new Pikaday({
    field: input,
    format: 'YYYY-MM-DD',
    defaultDate: new Date('2026-01-15'),
    setDefaultDate: true
});

Параметр setDefaultDate синхронизирует UI календаря с уже установленным значением, предотвращая расхождение состояния.


Обработка нескольких календарей в одной форме

Формы с большим количеством дат требуют унифицированного управления экземплярами Pikaday. Обычно используется массив конфигураций или фабрика инициализации:

const fields = document.querySelectorAll('.date-field');

fields.forEach(field => {
    new Pikaday({
        field,
        format: 'YYYY-MM-DD'
    });
});

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


Сериализация формы и подготовка данных к отправке

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

const form = document.getElementById('form');

form.addEventListener('submit', (e) => {
    const data = new FormData(form);

    const payload = {
        start: data.get('start'),
        end: data.get('end')
    };

    console.log(payload);
});

При необходимости можно дополнительно преобразовывать даты в timestamps:

const timestamp = new Date(data.get('start')).getTime();

Это обеспечивает совместимость с API, работающими в строгих форматах времени.


Интеграция с динамически создаваемыми формами

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

function createDateField(container) {
    const input = document.createElement('input');
    input.type = 'text';
    container.appendChild(input);

    return new Pikaday({
        field: input,
        format: 'YYYY-MM-DD'
    });
}

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


Согласованность состояния между UI и моделью формы

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

let state = {
    date: null
};

const picker = new Pikaday({
    field: input,
    onSelect(date) {
        state.date = date;
    }
});

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