import { Component } from '@angular/core';
import { WrDatePicker, WrDateRangePicker } from 'ngwr/date-picker';
@Component({ imports: [WrDatePicker, WrDateRangePicker] })
export class MyComponent {}Date Picker
A text field with a popup for picking a date, a time or both.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Basic
Bind [(value)]. The default format follows the locale.
<wr-date-picker [(value)]="picked" placeholder="Pick a date" />Custom format
format takes these tokens: yyyy yy MMMM MMM MM M dd d HH H hh h mm ss a.
<wr-date-picker [(value)]="picked" format="dd.MM.yyyy" />Bounds + filter
min and max are inclusive and dateFilter turns single dates off, for typed dates too.
<wr-date-picker
[(value)]="picked"
[min]="today"
[max]="firstOfNextMonth"
[dateFilter]="isWeekday"
/>Refused input
Unreadable text leaves the value unchanged and shows as invalid on Enter or blur; try 07.09.1994.
<wr-date-picker #dueField [(value)]="due" format="dd.MM.yyyy" [min]="today" />
@if (dueField.inputError(); as error) {
<small>{{ error.message }}</small>
}- The message comes from
validation.dateFormat,minDate,maxDateordateFilterin your i18n catalog. ngwr ships no text for them. - Without a form, read
inputError()through a template reference. - In a form, the control is invalid while the field holds refused text.
Time mode
mode="time" shows a time stepper instead of the calendar. The date part of the value is kept.
<wr-date-picker mode="time" [(value)]="picked" />Time — 24-hour
timeFormat="24h" forces the 24-hour clock, in the panel and in the field.
<wr-date-picker mode="time" timeFormat="24h" [(value)]="picked" />Time — seconds + step
showSeconds adds seconds to the panel and the field. step applies to minutes and seconds.
<wr-date-picker
mode="time"
timeFormat="24h"
[showSeconds]="true"
[step]="5"
[(value)]="picked"
/>Date + Time mode
mode="datetime" adds the time stepper under the calendar. Picking a date keeps the popup open.
<wr-date-picker mode="datetime" [(value)]="when" />Date + Time — custom format, seconds, step
<wr-date-picker
mode="datetime"
format="dd.MM.yyyy HH:mm:ss"
timeFormat="24h"
[showSeconds]="true"
[step]="5"
[(value)]="when"
/>Date range
<wr-date-range-picker> binds a [start, end] pair. Picking the second date closes the popup.
import { type WrDateRange, WrDateRangePicker } from 'ngwr/date-picker';
@Component({ imports: [WrDateRangePicker] })
export class MyComponent {
protected readonly period = signal<WrDateRange | null>(null);
}<wr-date-range-picker
[(value)]="period"
startPlaceholder="From"
endPlaceholder="To"
/>Date range + time
mode="datetime" adds a time stepper for each end. Picking dates keeps the popup open.
<wr-date-range-picker
mode="datetime"
timeFormat="24h"
format="dd.MM.yyyy HH:mm"
[(value)]="window"
/>Keyboard
The popup is not modal: Tab leaves it.
| Key | Does |
|---|---|
| Opens the popup and moves focus into it. | |
| Moves focus into a popup that is already open. | |
| Past the popup's last or first control: closes it and moves on from the trigger. | |
| Closes the popup and returns focus to what opened it. | |
| Accepts the typed text and closes the popup. A surrounding form still submits. |
Use it in a form
Bind [formField], formControlName or [(ngModel)]; see Forms.
<!-- Signal Forms -->
<wr-date-picker [formField]="form.due" />
<!-- Reactive forms -->
<form [formGroup]="form">
<wr-form-field label="Due date" required>
<wr-date-picker formControlName="due" placeholder="Pick a date" />
<wr-form-error key="required">Pick a due date.</wr-form-error>
</wr-form-field>
</form>
<!-- The range picker's value is WrDateRange | null. -->
<wr-date-range-picker formControlName="period" />
<!-- ngModel -->
<wr-date-picker [(ngModel)]="due" name="due" />import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { type WrDateRange, WrDatePicker, WrDateRangePicker } from 'ngwr/date-picker';
import { WrFormError, WrFormField } from 'ngwr/form';
@Component({
imports: [ReactiveFormsModule, WrFormField, WrFormError, WrDatePicker, WrDateRangePicker],
templateUrl: './my.html',
})
export class MyComponent {
protected readonly form = new FormGroup({
due: new FormControl<Date | null>(null, Validators.required),
period: new FormControl<WrDateRange | null>(null),
});
}API
| Name | Description | Type | Default |
|---|---|---|---|
mode | Picker behavior — see class doc. | 'date' | 'time' | 'datetime' | 'date' |
format | Format used for both display and parsing. When null (default), the format is derived from mode (shortDate / time / shortDateTime), with the hour cycle of timeFormat and the seconds of showSeconds (time24hSeconds, …). Pass a named key or raw token string to override. | WrDateFormat | string | null | null |
placeholder | Placeholder shown when the input is empty. | string | '' |
min | Min selectable date (forwarded to the calendar). Ignored in time mode. | Date | undefined | undefined |
max | Max selectable date (forwarded to the calendar). Ignored in time mode. | Date | undefined | undefined |
dateFilter | Predicate to disable specific dates (forwarded to the calendar). Ignored in time mode. | ((date: Date) => boolean) | null | null |
timeFormat | 12 / 24-hour clock, in the time panel and in the field, unless format is set. 'auto' follows the locale. Applies in time + datetime modes. | 'auto' | '12h' | '24h' | 'auto' |
showSeconds | Show seconds, in the time panel and in the field, unless format is set. Applies in time + datetime modes. | boolean | false |
step | Minute / second step for the time panel. | number | 1 |
disabled | Disable interaction. Bound automatically from the field's disabled state when used with [formField]. | boolean | false |
readonly | Read-only — input not typeable, but the trigger icon still opens the overlay. | boolean | false |
value | The picked Date. Bound by [formField], or two-way via [(value)]. | Date | null | null |
(touch) | Emitted on blur so a bound field can mark itself touched. | void | — |
ariaLabel | Accessible name of the text field. Falls back to the placeholder, then to the same catalog string the calendar button uses — the field is a role="combobox", and with an empty placeholder it had no name at all. | string | null | null |
panelAriaLabel | Accessible name of the popup. The trigger advertises aria-haspopup="dialog", so the panel is a role="dialog" — and an unnamed dialog announces as a bare "dialog". Defaults to the catalog's datePicker.panel* string for the current mode. | string | null | null |
panelClass | Extra CSS classes for the calendar panel's overlay pane. The pane is appended to the overlay container, not to this component, so nothing in the consumer's own template encloses it and no descendant rule written around the trigger can reach it. This input is the only per-instance handle on it. A space-separated string works as well as an array. | WrClassInput | null |
Range picker API
| Name | Description | Type | Default |
|---|---|---|---|
value | The range as [start, end]. An end is null until picked; ends in the wrong order are swapped. | WrDateRange | null | null |
mode | date (default) renders a range calendar; datetime adds a time stepper per end. | 'date' | 'datetime' | 'date' |
format | Format for both ends. Defaults to shortDate, or shortDateTime with the clock of timeFormat and showSeconds. | WrDateFormat | string | null | null |
startPlaceholder | Placeholder for the start input. | string | '' |
endPlaceholder | Placeholder for the end input. | string | '' |
separator | Glyph rendered between the two inputs. | string | '–' |
minDate | Earliest selectable date, for both ends. Not min, unlike <wr-date-picker>. | Date | null | null |
maxDate | Latest selectable date, for both ends. | Date | null | null |
dateFilter | Predicate disabling individual dates. | ((date: Date) => boolean) | null | null |
timeFormat | 12 / 24-hour clock, in the time panels and both fields. Applies in datetime mode. | 'auto' | '12h' | '24h' | 'auto' |
showSeconds | Show seconds on both time panels and in both fields. | boolean | false |
step | Minute / second step for the time panels. | number | 1 |
disabled | Block interaction. | boolean | false |
panelAriaLabel | Accessible name of the popup. Defaults to the catalog’s datePicker.panelRange* string for the mode. | string | null | null |
panelClass | Extra classes for the popup’s overlay pane, as a string or an array. | WrClassInput | null |
(touch) | Emitted on blur so a bound field can mark itself touched. | void | — |
readonly | The value cannot change and the popup does not open. <wr-date-picker> still opens its popup. | boolean | false |
CSS variables
Set these on the component's selector or a wrapper, not on :root: the defaults are declared on ngwr/date-picker's own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-date-range-panel-time-gap | var(--wr-space-xs) | .wr-date-range-panel__time |
--wr-date-range-panel-time-label-font-size | var(--wr-text-xs) | .wr-date-range-panel__time-label |
--wr-date-range-panel-time-label-font-weight | var(--wr-font-weight-semibold) | .wr-date-range-panel__time-label |
--wr-date-range-panel-times-border | var(--wr-border-base) | .wr-date-range-panel__times |
--wr-date-range-panel-times-gap-x | var(--wr-space-xl) | .wr-date-range-panel__times |
--wr-date-range-panel-times-gap-y | var(--wr-space-md) | .wr-date-range-panel__times |
--wr-date-range-panel-times-padding | var(--wr-space-md) | .wr-date-range-panel__times |
--wr-date-range-panel-times-radius | var(--wr-border-radius-base) | .wr-date-range-panel__times |
--wr-date-range-picker-separator-padding-x | var(--wr-space-xs) | .wr-date-range-picker__separator |
--wr-date-time-panel-time-border | var(--wr-border-base) | .wr-date-time-panel__time |
--wr-date-time-panel-time-padding | var(--wr-space-md) | .wr-date-time-panel__time |
--wr-date-time-panel-time-radius | var(--wr-border-radius-base) | .wr-date-time-panel__time |
--wr-time-picker-bg | var(--wr-color-surface) | .wr-time-picker |
--wr-time-picker-border | var(--wr-border-base) | .wr-time-picker |
--wr-time-picker-col-gap | var(--wr-space-xs) | .wr-time-picker__col |
--wr-time-picker-col-width | 3rem | .wr-time-picker |
--wr-time-picker-color | var(--wr-color-on-surface) | .wr-time-picker |
--wr-time-picker-font-family | var(--wr-font-family-base) | .wr-time-picker |
--wr-time-picker-gap | var(--wr-space-xs) | .wr-time-picker |
--wr-time-picker-input-font-size | var(--wr-text-sm) | .wr-time-picker__input |
--wr-time-picker-input-font-weight | var(--wr-font-weight-semibold) | .wr-time-picker__input |
--wr-time-picker-input-line-height | var(--wr-text-sm-leading) | .wr-time-picker__input |
--wr-time-picker-input-padding | var(--wr-space-xs) | .wr-time-picker__input |
--wr-time-picker-input-radius | var(--wr-border-radius-sm) | .wr-time-picker__input |
--wr-time-picker-label-font-size | var(--wr-text-sm) | .wr-time-picker |
--wr-time-picker-label-font-weight | var(--wr-font-weight-semibold) | .wr-time-picker |
--wr-time-picker-label-radius | var(--wr-border-radius-sm) | .wr-time-picker |
--wr-time-picker-muted | var(--wr-color-on-surface-muted) | .wr-time-picker |
--wr-time-picker-overlay-padding-x | var(--wr-space-md) | .wr-date-picker-overlay > .wr-time-picker |
--wr-time-picker-overlay-padding-y | var(--wr-space-sm) | .wr-date-picker-overlay > .wr-time-picker |
--wr-time-picker-overlay-radius | var(--wr-border-radius-base) | .wr-date-picker-overlay > .wr-time-picker |
--wr-time-picker-sep-font-size | var(--wr-text-lg) | .wr-time-picker__sep |
--wr-time-picker-sep-font-weight | var(--wr-font-weight-semibold) | .wr-time-picker__sep |
--wr-time-picker-sep-line-height | var(--wr-leading-none) | .wr-time-picker__sep |
--wr-time-picker-sep-padding-top | var(--wr-space-sm) | .wr-time-picker__sep |
--wr-time-picker-step-line-height | var(--wr-leading-none) | .wr-time-picker__step |
--wr-time-picker-step-radius | var(--wr-border-radius-sm) | .wr-time-picker__step |
Dependencies
| Angular CDK | overlay, portal |
|---|---|
| Built on | Calendar, ngwr/date, Form, Input, Overlay |
| Used by | Schema Form |
See also
Component CalendarA month calendar for picking a date or a date range.Component Form FieldWraps a form control with a label, a hint and its error messages.Guide FormsBind ngwr controls to any Angular form and show their errors.Docs ConfigurationSet app-wide options at bootstrap.Validator minDateReject a date before min.Validator maxDateReject a date after max.Component FormA plain layout wrapper for a label, a control and its error.Component InputA directive that styles a native <input> or <textarea>.