Skip to main content

BwDatepicker | bw-datepicker

This component is experimental and it's public api is subject to change

Overview

An inline date / time picker. It renders a month calendar and/or time columns and reports the selected value as epoch milliseconds. It is fluid — it fills the width of its container — so it works inline, inside a bw-card, or as the content of a bw-popover to build a field-style picker with bw-input.

Usage

Basics

bw-datepicker is an inline picker. Choose what it shows with type: a calendar (date), a calendar plus time columns (datetime, the default), or time only (time).

<div class="flex-row gap" style="flex-wrap: wrap; align-items: flex-start;">
<bw-card><bw-datepicker type="date"></bw-datepicker></bw-card>
<bw-card><bw-datepicker type="time"></bw-datepicker></bw-card>
</div>

Reading the value

The selected value is epoch milliseconds. bw-datepicker emits valueChange (and updates its value property) whenever the selection changes.

<div class="flex-column gap">
<bw-card><bw-datepicker id="dpRead" type="datetime"></bw-datepicker></bw-card>
<bw-note id="dpReadOut">Nothing selected yet</bw-note>
</div>
<script>
const dp = document.getElementById('dpRead');
const out = document.getElementById('dpReadOut');
dp.addEventListener('valueChange', e => {
out.textContent = e.detail ? new Date(e.detail).toLocaleString() : 'Nothing selected yet';
});
</script>

Setting an initial value

value is a number, so set it as a property in JavaScript. The picker opens to that date and marks it selected.

<bw-card><bw-datepicker id="dpInit" type="date"></bw-datepicker></bw-card>
<script>
document.getElementById('dpInit').value = Date.now();
</script>

Constraints

Limit the selectable range with min and max (both epoch ms). Days outside the range are disabled.

<bw-card><bw-datepicker id="dpRange" type="date"></bw-datepicker></bw-card>
<script>
const dp = document.getElementById('dpRange');
const now = Date.now();
dp.min = now;
//30 days
dp.max = now + 30 * 24 * 60 * 60 * 1000;
</script>

Disabling specific days

For finer control, pass an isDateDisabled predicate (a property, since it's a function). Return true to disable a day — here, weekends.

<bw-card><bw-datepicker id="dpWeekdays" type="date"></bw-datepicker></bw-card>
<script>
const dp = document.getElementById('dpWeekdays');
dp.isDateDisabled = (date) => {
const day = date.getDay();
return day === 0 || day === 6; // Sun / Sat
};
</script>

Seconds

For time and datetime, set include-seconds to add a seconds column.

<bw-card><bw-datepicker type="time" include-seconds></bw-datepicker></bw-card>

In a Field

bw-datepicker is an inline picker, but the common form pattern is an editable field that also opens a picker. Compose it from a bw-popover (the picker as its content) and a bw-input with the datetime mask as its trigger. The two stay in sync: typing MM/DD/YYYY HH:mm moves the picker, and choosing a day/time in the picker fills the field.

<bw-popover id="dpFieldPop" placement="bottom-start">
<bw-input slot="trigger" id="dpFieldInput" type="datetime" label="Appointment" placeholder="MM/DD/YYYY HH:mm">
<bw-icon slot="start">calendar_month</bw-icon>
</bw-input>
<bw-card>
<bw-datepicker id="dpFieldPicker" type="datetime"></bw-datepicker>
</bw-card>
</bw-popover>
<script>
const picker = document.getElementById('dpFieldPicker');
const input = document.getElementById('dpFieldInput');
const pad = n => String(n).padStart(2, '0');
let syncing = false;

// Picker → field: write the date as the mask's raw digits (MMDDYYYYHHmm).
picker.addEventListener('valueChange', e => {
if (syncing) return;
syncing = true;
const d = e.detail != null ? new Date(e.detail) : null;
input.value = d
? `${pad(d.getMonth() + 1)}${pad(d.getDate())}${d.getFullYear()}${pad(d.getHours())}${pad(d.getMinutes())}`
: '';
syncing = false;
});

// Field → picker: once a full MM/DD/YYYY HH:mm is typed, move the picker.
input.addEventListener('valueChange', e => {
if (syncing) return;
const g = String(e.detail || '').replace(/\D/g, '');
if (g.length !== 12) return;
const date = new Date(+g.slice(4, 8), +g.slice(0, 2) - 1, +g.slice(2, 4), +g.slice(8, 10), +g.slice(10, 12));
if (!isNaN(date)) { syncing = true; picker.value = date.getTime(); syncing = false; }
});
</script>

How it fits together:

  • type="datetime" on the input applies a datetime mask — the user types digits and the field formats them as MM/DD/YYYY HH:mm. The input's value is the raw 12-digit string, which is easy to parse.
  • A syncing guard prevents the two valueChange handlers from looping when one updates the other.
  • The picker's value is the source of truth (epoch ms). Store or submit that; the field is just a fast text entry path into it.
  • type="datetime" on the picker keeps the popover open so the user can pick the time after the day. For a date-only field, close the popover once a day is chosen:
picker.addEventListener('valueChange', e => {
document.querySelector('bw-popover').open = false; // dismiss after selection
});

Time Zones

By default the picker displays times in the browser's time zone. Set time-zone to an IANA zone to display and select in a fixed zone instead — the emitted value is still epoch milliseconds, only the displayed clock changes.

<bw-card><bw-datepicker id="dpTz" type="datetime" time-zone="Asia/Tokyo"></bw-datepicker></bw-card>
<script>
document.getElementById('dpTz').value = Date.now();
</script>

Properties

PropertyAttributeDescriptionTypeDefault
includeSecondsinclude-secondsInclude a seconds column in the time picker (time / datetime).booleanfalse
isDateDisabled--Predicate to disable individual days — return true to disable the given date.(date: Date) => booleanundefined
maxmaxLatest selectable instant (epoch ms). Days after it are disabled.numberundefined
minminEarliest selectable instant (epoch ms). Days before it are disabled.numberundefined
timeZonetime-zoneIANA time zone used for display (e.g. America/New_York). Defaults to the browser zone.stringundefined
typetypeWhich controls to show: a calendar (date), calendar + time (datetime), or just time (time)."date" | "datetime" | "time"'datetime'
valuevalueThe selected value (epoch ms). Mutable and two-way via valueChange.numberundefined

Events

EventDescriptionType
valueChangeEmitted when the selected value changes. Detail is the new value (epoch ms) or undefined.CustomEvent<number>

Dependencies

Used by

Depends on

Graph


© 2025 United Systems & Software - All Rights Reserved.