Forms Date Picker

Date Picker

An accessible, flexible date picker built on wf-date-picker.js . Renders as a fixed-position dropdown or an always-visible inline calendar. Supports single dates, linked date ranges, custom display and submit formats, min/max constraints, disabled weekdays and date ranges, and optional footer action buttons. A hidden 'submit' input is created automatically so selected values participate in standard form submissions.

Quick Start

Import the module once. All elements with data-wf-datepicker are enhanced automatically on DOMContentLoaded . The component decorates the inner <input> and appends a calendar icon and a hidden 'submit' input ( name_submit ) automatically.

JS
import './wf-date-picker.js'
HTML
<!-- Auto-init (dropdown) -->
<div class="wf-datepicker" data-wf-datepicker>
  <input type="text" name="birth_date" placeholder="Select date">
</div>

<!-- Manual init -->
<div class="wf-datepicker" id="my-dp">
  <input type="text" name="event_date">
</div>
<script type="module">
  import { WojoDatePicker } from './wf-date-picker.js'
  new WojoDatePicker(document.getElementById('my-dp')).init()
</script>

Format Tokens

Use data-wf-format to control how the date is shown in the visible input. The default is mm/dd/yyyy . Use data-wf-format-submit to control the hidden 'submit' value (default: yyyy-mm-dd ). Any combination of the tokens below is supported, separated by any non-letter character. Tokens: dd, mm, mmm, mmmm, yy, yyyy, d, m .

HTML
<div class="wf-datepicker" data-wf-datepicker data-wf-format="dd/mm/yyyy">
  <input type="text" name="date">
</div>

<div class="wf-datepicker" data-wf-datepicker data-wf-format="mmmm d, yyyy">
  <input type="text" name="date">
</div>

<div class="wf-datepicker" data-wf-datepicker data-wf-format="D, mmm dd yyyy">
  <input type="text" name="date">
</div>
Token Output Example
yyyy Full 4-digit year 2025
yy 2-digit year 25
mmmm Full month name January
mmm Short month name Jan
mm Zero-padded month 01-12
m Month number 1-12
dd Zero-padded day 01-31
d Day number 1-31
DD Full weekday name Monday
D Short weekday name Mon

Constraints

Restrict the selectable range with data-wf-min-date and data-wf-max-date (use the display format or the special value "today" ). Disable specific weekdays with data-wf-disabled-days (semicolon-separated, 0=Sun) and specific dates or ranges with data-wf-disabled-dates . Change the first day of the week with data-wf-week-start .

HTML
<!-- Future dates only -->
<div class="wf-datepicker" data-wf-datepicker data-wf-min-date="today">
  <input type="text" name="start_date">
</div>

<!-- Weekdays only, week starts Monday -->
<div class="wf-datepicker" data-wf-datepicker
     data-wf-disabled-days="0;6"
     data-wf-week-start="1">
  <input type="text" name="booking_date">
</div>

<!-- Min/max range -->
<div class="wf-datepicker" data-wf-datepicker
     data-wf-min-date="01/01/2025"
     data-wf-max-date="12/31/2025">
  <input type="text" name="year_date">
</div>

<!-- Disable specific dates and a date range -->
<div class="wf-datepicker" data-wf-datepicker
     data-wf-disabled-dates="06/25/2025;07/04/2025|07/07/2025">
  <input type="text" name="available_date">
</div>

Footer Buttons

Add data-wf-buttons to show Today and Clear buttons in the panel footer. Use data-wf-ok-btn to defer the close until the user confirms, and data-wf-cancel-btn to add a Cancel button. Add a heading above the calendar with data-wf-title .

HTML
<!-- Today + Clear buttons -->
<div class="wf-datepicker" data-wf-datepicker data-wf-buttons>
  <input type="text" name="date">
</div>

<!-- OK + Cancel with a panel title -->
<div class="wf-datepicker" data-wf-datepicker
     data-wf-ok-btn
     data-wf-cancel-btn
     data-wf-title="Choose a date">
  <input type="text" name="date">
</div>

Date Range

Link two pickers to form a range. The start picker gets data-wf-range-to="#end-id" and the end picker gets data-wf-range-from="#start-id" . When a start date is selected, earlier dates are automatically disabled in the end picker, and both calendars re-render to show the highlighted range.

HTML
<div class="wf-datepicker" id="dp-start"
     data-wf-datepicker
     data-wf-range-to="#dp-end">
  <input type="text" name="start" placeholder="Start date">
</div>

<div class="wf-datepicker" id="dp-end"
     data-wf-datepicker
     data-wf-range-from="#dp-start">
  <input type="text" name="end" placeholder="End date">
</div>

Inline

Add data-wf-inline for a calendar that is always visible with no input trigger. Use a type="hidden" input to capture the value for form submission. All other options (constraints, buttons, range) apply equally.

HTML
<div class="wf-datepicker" data-wf-datepicker data-wf-inline data-wf-buttons>
  <input type="hidden" name="selected_date">
</div>

Data Attributes

All configuration is applied via data-wf-* attributes on the .wf-datepicker wrapper.

Attribute Type Default Description
data-wf-datepicker Boolean - Required. Marks the wrapper for auto-init.
data-wf-format String mm/dd/yyyy Display format for the visible input. Supports tokens: yyyy yy mmmm mmm mm m dd d DD D.
data-wf-format-submit String yyyy-mm-dd Format written to the hidden 'submit' input.
data-wf-autohide Boolean true Auto-close the panel when a day is selected. Set false to keep it open.
data-wf-buttons Boolean - Show Today and Clear buttons in the panel footer.
data-wf-ok-btn Boolean - Show an OK button; defers the panel close until it is clicked.
data-wf-cancel-btn Boolean - Show a Cancel button that closes without committing.
data-wf-title String - Optional heading is displayed above the navigation row.
data-wf-min-date String - Earliest selectable date in the display format, or "today".
data-wf-max-date String - Latest selectable date in the display format, or "today".
data-wf-disabled-days String - Semicolon-separated weekday numbers to disable. 0=Sun, 6=Sat. E.g. "0;6" disables weekends.
data-wf-disabled-dates String - Semicolon-separated dates or ranges. Range syntax: start|end. E.g. "06/25/2025;07/04/2025|07/07/2025".
data-wf-week-start Number 0 First day of the week. 0=Sun (default), 1=Mon.
data-wf-inline Boolean - Always-visible inline calendar with no input trigger or dropdown.
data-wf-disabled Boolean - Disable all picker interaction.
data-wf-range-to String - CSS selector of the END picker wrapper. Marks this picker as the range START.
data-wf-range-from String - CSS selector of the START picker wrapper. Marks this picker as the range END.
Show More

Events & API

Access the instance via el._wfDatePicker . Global defaults can be set before any pickers initialize with WojoDatePicker.setDefaults() .

Methods

Method Returns Description
WojoDatePicker.setDefaults(opts) - Set global defaults (format, formatSubmit, weekStart) for all future instances and any already-initialized pickers without a per-instance override.
dp.show() - Open the calendar panel.
dp.hide() - Close the calendar panel.
dp.toggle() - Toggle open/closed.
dp.getDate() Date | null Returns the currently selected Date object, or null.
dp.setDate(str) this Set the date from a string. Accepts the current display format or an ISO yyyy-mm-dd string.
dp.clearDate() this Clear the current selection and reset both inputs.
dp.setDisabled(bool) this Enable or disable the picker. Toggles wf-datepicker--disabled.
dp.destroy() - Remove all event listeners, detach the panel from the DOM, and delete el._wfDatePicker.

Events

All events are dispatched on the .wf-datepicker wrapper element.

Event Detail Description
wf:date-change { date: Date|null, value: string|null } Fired when a date is committed. date is the Date object; value is the formatted display string. Both are null after clearDate(). A native change event is also fired on the inner input.
wf:date-show - Fired when the dropdown panel opens.
wf:date-hide - Fired when the dropdown panel closes.
JS
// Set global defaults before init
WojoDatePicker.setDefaults({ format: 'dd/mm/yyyy', weekStart: 1 })

// Access instance
const wrapper = document.querySelector('#my-dp')
const dp = wrapper._wfDatePicker

// Programmatic control
dp.setDate('06/15/2025')   // set by display format string
dp.setDate('2025-06-15')   // or ISO yyyy-mm-dd
dp.getDate()               // -> Date object or null
dp.clearDate()             // clear selection
dp.setDisabled(true)       // disable
dp.show()                  // open panel
dp.hide()                  // close panel
dp.destroy()               // remove component

// Listen for changes
wrapper.addEventListener('wf:date-change', e => {
  console.log(e.detail.date)    // Date object or null
  console.log(e.detail.value)   // formatted string or null
})