Overview for datepicker

The datepicker allows users to enter a date either through text input, or by choosing a date from the calendar. It is made up of several components, directives and the date implementation that work together.

Basic datepicker
MM/DD/YYYY

A datepicker is composed of a text input and a calendar pop-up, connected via the matDatepicker property on the text input.

There is also an optional datepicker toggle button that gives the user an easy way to open the datepicker pop-up.

<input matInput [matDatepicker]="picker">
<mat-hint>MM/DD/YYYY</mat-hint>
<mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>

This works exactly the same with an input that is part of an <mat-form-field> and the toggle can easily be used as a prefix or suffix on the Material input:

<mat-form-field>
  <mat-label>Choose a date</mat-label>
  <input matInput [matDatepicker]="picker">
  <mat-hint>MM/DD/YYYY</mat-hint>
  <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

If you want to customize the icon that is rendered inside the mat-datepicker-toggle, you can do so by using the matDatepickerToggleIcon directive:

Datepicker with custom icon
MM/DD/YYYY

If you want your users to select a range of dates, instead of a single date, you can use the mat-date-range-input and mat-date-range-picker components. They work in tandem, similarly to the mat-datepicker and the basic datepicker input.

The mat-date-range-input component requires two input elements for the start and end dates, respectively:

<mat-date-range-input>
  <input matStartDate placeholder="Start date">
  <input matEndDate placeholder="End date">
</mat-date-range-input>

The mat-date-range-picker component acts as the pop-up panel for selecting dates. This works in the same way as mat-datepicker, but allows the user to select multiple times:

<mat-date-range-picker #picker></mat-date-range-picker>

Connect the range picker and range input using the rangePicker property:

<mat-date-range-input [rangePicker]="picker">
  <input matStartDate placeholder="Start date">
  <input matEndDate placeholder="End date">
</mat-date-range-input>

<mat-date-range-picker #picker></mat-date-range-picker>
Basic date range picker
MM/DD/YYYY – MM/DD/YYYY

The mat-date-range-input component can be used together with the FormGroup directive from @angular/forms to group the start and end values together and to validate them as a group.

Date range picker forms integration
MM/DD/YYYY – MM/DD/YYYY

Selected range: { "start": null, "end": null }

The startView property of <mat-datepicker> can be used to set the view that will show up when the calendar first opens. It can be set to month, year, or multi-year; by default it will open to month view.

The month, year, or range of years that the calendar opens to is determined by first checking if any date is currently selected, if so it will open to the month or year containing that date. Otherwise it will open to the month or year containing today's date. This behavior can be overridden by using the startAt property of <mat-datepicker>. In this case the calendar will open to the month or year containing the startAt date.

Datepicker start date
MM/DD/YYYY

When a year or a month is selected in multi-year and year views respectively, the yearSelected and monthSelected outputs emit a normalized date representing the chosen year or month. By "normalized" we mean that the dates representing years will have their month set to January and their day set to the 1st. Dates representing months will have their day set to the 1st of the month. For example, if <mat-datepicker> is configured to work with javascript native Date objects, the yearSelected will emit new Date(2017, 0, 1) if the user selects 2017 in multi-year view. Similarly, monthSelected will emit new Date(2017, 1, 1) if the user selects February in year view and the current date value of the connected <input> was set to something like new Date(2017, MM, dd) when the calendar was opened (the month and day are irrelevant in this case).

Notice that the emitted value does not affect the current value in the connected <input>, which is only bound to the selection made in the month view. So if the end user closes the calendar after choosing a year in multi-view mode (by pressing the ESC key, for example), the selected year, emitted by yearSelected output, will not cause any change in the value of the date in the associated <input>.

The following example uses yearSelected and monthSelected outputs to emulate a month and year picker (if you're not familiar with the usage of MomentDateAdapter and MAT_DATE_FORMATS you can read more about them below in this document to fully understand the example).

Datepicker emulating a Year and month picker
MM/YYYY

The type of values that the datepicker expects depends on the type of DateAdapter provided in your application. The NativeDateAdapter, for example, works directly with plain JavaScript Date objects. When using the MomentDateAdapter, however, the values will all be Moment.js instances. This use of the adapter pattern allows the datepicker component to work with any arbitrary date representation with a custom DateAdapter. See Choosing a date implementation for more information.

Depending on the DateAdapter being used, the datepicker may automatically deserialize certain date formats for you as well. For example, both the NativeDateAdapter and MomentDateAdapter allow ISO 8601 strings to be passed to the datepicker and automatically converted to the proper object type. This can be convenient when binding data directly from your backend to the datepicker. However, the datepicker will not accept date strings formatted in user format such as "1/2/2017" as this is ambiguous and will mean different things depending on the locale of the browser running the code.

As with other types of <input>, the datepicker works with @angular/forms directives such as formGroup, formControl, ngModel, etc.

Datepicker selected value
MM/DD/YYYY
MM/DD/YYYY
MM/DD/YYYY

There are three properties that add date validation to the datepicker input. The first two are the min and max properties. In addition to enforcing validation on the input, these properties will disable all dates on the calendar popup before or after the respective values and prevent the user from advancing the calendar past the month or year (depending on current view) containing the min or max date.

Datepicker with min & max validation
MM/DD/YYYY

The second way to add date validation is using the matDatepickerFilter property of the datepicker input. This property accepts a function of <D> => boolean (where <D> is the date type used by the datepicker, see Choosing a date implementation). A result of true indicates that the date is valid and a result of false indicates that it is not. Again this will also disable the dates on the calendar that are invalid. However, one important difference between using matDatepickerFilter vs using min or max is that filtering out all dates before or after a certain point, will not prevent the user from advancing the calendar past that point.

Datepicker with filter validation
MM/DD/YYYY

In this example the user cannot select any date that falls on a Saturday or Sunday, but all of the dates which fall on other days of the week are selectable.

Each validation property has a different error that can be checked:

  • A value that violates the min property will have a matDatepickerMin error.
  • A value that violates the max property will have a matDatepickerMax error.
  • A value that violates the matDatepickerFilter property will have a matDatepickerFilter error.

The input's native (input) and (change) events will only trigger due to user interaction with the input element; they will not fire when the user selects a date from the calendar popup. Therefore, the datepicker input also has support for (dateInput) and (dateChange) events. These trigger when the user interacts with either the input or the popup.

The (dateInput) event will fire whenever the value changes due to the user typing or selecting a date from the calendar. The (dateChange) event will fire whenever the user finishes typing input (on <input> blur), or when the user chooses a date from the calendar.

Datepicker input and change events
MM/DD/YYYY

As with any standard <input>, it is possible to disable the datepicker input by adding the disabled property. By default, the <mat-datepicker> and <mat-datepicker-toggle> will inherit their disabled state from the <input>, but this can be overridden by setting the disabled property on the datepicker or toggle elements. This can be useful if you want to disable text input but allow selection via the calendar or vice-versa.

Disabled datepicker

MM/DD/YYYY

MM/DD/YYYY

MM/DD/YYYY

By default, clicking on a date in the calendar will select it and close the calendar popup. In some cases this may not be desirable, because the user doesn't have a quick way of going back if they've changed their mind. If you want your users to be able to cancel their selection and to have to explicitly accept the value that they've selected, you can add a <mat-datepicker-actions> element inside <mat-datepicker> with a "Cancel" and an "Apply" button marked with the matDatepickerCancel and matDatepickerApply attributes respectively. Doing so will cause the datepicker to only assign the value to the data model if the user presses "Apply", whereas pressing "Cancel" will close popup without changing the value.

<mat-datepicker #datepicker>
  <mat-datepicker-actions>
    <button mat-button matDatepickerCancel>Cancel</button>
    <button mat-raised-button matDatepickerApply>Apply</button>
  </mat-datepicker-actions>
</mat-datepicker>

The actions element is also supported for <mat-date-range-picker> where that it is called <mat-date-range-picker-actions> and the buttons are called matDateRangePickerCancel and matDateRangePickerApply respectively.

<mat-date-range-picker #rangePicker>
  <mat-date-range-picker-actions>
    <button mat-button matDateRangePickerCancel>Cancel</button>
    <button mat-raised-button matDateRangePickerApply>Apply</button>
  </mat-date-range-picker-actions>
</mat-date-range-picker>
Datepicker action buttons
MM/DD/YYYY
MM/DD/YYYY – MM/DD/YYYY

If your users need to compare the date range that they're currently selecting with another range, you can provide the comparison range start and end dates to the mat-date-range-input using the comparisonStart and comparisonEnd bindings. The comparison range will be rendered statically within the calendar, but it will change colors to indicate which dates overlap with the user's selected range. The comparison and overlap colors can be customized using the datepicker-date-range-colors mixin.

Date range picker comparison ranges
MM/DD/YYYY – MM/DD/YYYY
MM/DD/YYYY – MM/DD/YYYY
@use '@angular/material' as mat;

@include mat.datepicker-date-range-colors(hotpink, teal, yellow, purple);

The mat-date-range-picker supports custom behaviors for range previews and selection. To customize this, you first create a class that implements MatDateRangeSelectionStrategy, and then provide the class via the MAT_DATE_RANGE_SELECTION_STRATEGY injection token. The following example uses the range selection strategy to create a custom range picker that limits the user to five-day ranges.

Date range picker with a custom selection strategy
MM/DD/YYYY – MM/DD/YYYY

The datepicker normally opens as a popup under the input. However this is not ideal for touch devices that don't have as much screen real estate and need bigger click targets. For this reason <mat-datepicker> has a touchUi property that can be set to true in order to enable a more touch friendly UI where the calendar opens in a large dialog.

Datepicker touch UI
MM/DD/YYYY

The calendar popup can be programmatically controlled using the open and close methods on the <mat-datepicker>. It also has an opened property that reflects the status of the popup.

Datepicker open method
MM/DD/YYYY

If you want to allow the user to select a date from a calendar that is inlined on the page rather than contained in a popup, you can use <mat-calendar> directly. The calendar's height is determined automatically based on the width and the number of dates that need to be shown for a month. If you want to make the calendar larger or smaller, adjust the width rather than the height.

Datepicker inline calendar example
FEB 2025
Comparison range Comparison range
SundayMondayTuesdayWednesdayThursdayFridaySaturday
FEB

Selected date:

Internationalization of the datepicker is configured via four aspects:

  1. The date locale.
  2. The date implementation that the datepicker accepts.
  3. The display and parse formats used by the datepicker.
  4. The message strings used in the datepicker's UI.

By default, the MAT_DATE_LOCALE injection token will use the existing LOCALE_ID locale code from @angular/core. If you want to override it, you can provide a new value for the MAT_DATE_LOCALE token:

bootstapApplication(MyApp, {
  providers: [{provide: MAT_DATE_LOCALE, useValue: 'en-GB'}],
});

It's also possible to set the locale at runtime using the setLocale method of the DateAdapter.

Note: if you're using the provideDateFnsAdapter, you have to provide the data object for your locale to MAT_DATE_LOCALE instead of the locale code, in addition to providing a configuration compatible with date-fns to MAT_DATE_FORMATS. Locale data for date-fns can be imported from date-fns/locale.

Datepicker with different locale
YYYY/MM/DD

The datepicker was built to be date implementation agnostic. This means that it can be made to work with a variety of different date implementations. However it also means that developers need to make sure to provide the appropriate pieces for the datepicker to work with their chosen implementation.

The easiest way to ensure this is to import one of the provided date adapters:

provideNativeDateAdapter or MatNativeDateModule

Date type Date
Supported locales en-US
Dependencies None
Import from @angular/material/core

provideDateFnsAdapter or MatDateFnsModule (installed via ng add @angular/material-date-fns-adapter)

Date type Date
Supported locales See project for details
Dependencies date-fns
Import from @angular/material-date-fns-adapter

provideLuxonDateAdapter or MatLuxonDateModule (installed via ng add @angular/material-luxon-adapter)

Date type DateTime
Supported locales See project for details
Dependencies Luxon
Import from @angular/material-luxon-adapter

provideMomentDateAdapter or MatMomentDateModule (installed via ng add @angular/material-moment-adapter)

Date type Moment
Supported locales See project for details
Dependencies Moment.js
Import from @angular/material-moment-adapter

Please note: provideNativeDateAdapter is based off the functionality available in JavaScript's native Date object. Thus it is not suitable for many locales. One of the biggest shortcomings of the native Date object is the inability to set the parse format. We strongly recommend using an adapter based on a more robust formatting and parsing library. You can use provideMomentDateAdapter or a custom DateAdapter that works with the library of your choice.

These APIs include providers for DateAdapter and MAT_DATE_FORMATS.

bootstrapApplication(MyApp, {
  providers: [provideNativeDateAdapter()]
});

Because DateAdapter is a generic class, MatDatepicker and MatDatepickerInput also need to be made generic. When working with these classes (for example as a ViewChild) you should include the appropriate generic type that corresponds to the DateAdapter implementation you are using. For example:

@Component({...})
export class MyComponent {
  @ViewChild(MatDatepicker) datepicker: MatDatepicker<Date>;
}
Datepicker that uses Moment.js dates
MM/DD/YYYY

By default the MomentDateAdapter creates dates in your time zone specific locale. You can change the default behaviour to parse dates as UTC by passing useUtc: true into provideMomentDateAdapter or by providing the MAT_MOMENT_DATE_ADAPTER_OPTIONS injection token.

bootstrapApplication(MyApp, {
  providers: [provideMomentDateAdapter(undefined, {useUtc: true})]
});

By default the MomentDateAdapter will parse dates in a forgiving way. This may result in dates being parsed incorrectly. You can change the default behaviour to parse dates strictly by strict: true to provideMomentDateAdapter or by providing the MAT_MOMENT_DATE_ADAPTER_OPTIONS injection token.

bootstrapApplication(MyApp, {
  providers: [provideMomentDateAdapter(undefined, {strict: true})]
});

It is also possible to create your own DateAdapter that works with any date format your app requires. This is accomplished by subclassing DateAdapter and providing your subclass as the DateAdapter implementation. You will also want to make sure that the MAT_DATE_FORMATS provided in your app are formats that can be understood by your date implementation. See Customizing the parse and display formats for more information about MAT_DATE_FORMATS.

bootstrapApplication(MyApp, {
  providers: [
    {provide: DateAdapter, useClass: MyDateAdapter},
    {provide: MAT_DATE_FORMATS, useValue: MY_DATE_FORMATS},
  ]
});

If you need to work with native Date objects, but need custom behavior (for example custom date parsing), you can consider subclassing NativeDateAdapter.

The MAT_DATE_FORMATS object is a collection of formats that the datepicker uses when parsing and displaying dates. These formats are passed through to the DateAdapter so you will want to make sure that the format objects you're using are compatible with the DateAdapter used in your app.

If you want use one of the DateAdapters that ships with Angular Material, but use your own MAT_DATE_FORMATS, you can either pass the formats into the providers function, or provide the MAT_DATE_FORMATS token yourself. For example:

bootstrapApplication(MyApp, {
  providers: [provideNativeDateAdapter(MY_NATIVE_DATE_FORMATS)],
});
Datepicker with custom formats
MMMM DD, YYYY

To use custom formats with the provideMomentDateAdapter you can pick from the parse formats documented here and the display formats documented here.

It is also possible to support multiple parse formats. For example:

bootstraApplication(MyApp, {
  providers: [provideMomentDateAdapter({
    parse: {
      dateInput: ['l', 'LL'],
    },
    display: {
      dateInput: 'L',
      monthYearLabel: 'MMM YYYY',
      dateA11yLabel: 'LL',
      monthYearA11yLabel: 'MMMM YYYY',
    },
  })]
});

The header section of the calendar (the part containing the view switcher and previous and next buttons) can be replaced with a custom component if desired. This is accomplished using the calendarHeaderComponent property of <mat-datepicker>. It takes a component class and constructs an instance of the component to use as the header.

In order to interact with the calendar in your custom header component, you can inject the parent MatCalendar in the constructor. To make sure your header stays in sync with the calendar, subscribe to the stateChanges observable of the calendar and mark your header component for change detection.

Datepicker with custom calendar header
MM/DD/YYYY

The various text strings used by the datepicker are provided through MatDatepickerIntl. Localization of these messages can be done by providing a subclass with translated values in your app config.

bootstrapApplication(MyApp, {
  providers: [
    {provide: MatDatepickerIntl, useClass: MyIntl},
    provideNativeDateAdapter(),
  ],
});

If you want to apply one or more CSS classes to some dates in the calendar (e.g. to highlight a holiday), you can do so with the dateClass input. It accepts a function which will be called with each of the dates in the calendar and will apply any classes that are returned. The return value can be anything that is accepted by ngClass.

Datepicker with custom date classes
MM/DD/YYYY

The MatDatepicker pop-up uses the role="dialog" interaction pattern. This dialog then contains multiple controls, the most prominent being the calendar itself. This calendar implements the role="grid" interaction pattern.

Always enable confirmation action buttons. This allows assistive technology users to explicitly confirm their selection before committing a value.

The MatDatepickerInput and MatDatepickerToggle directives both apply the aria-haspopup attribute to the native input and button elements, respectively.

MatDatepickerIntl includes strings that are used for aria-label attributes. Always provide the datepicker text input a meaningful label via <mat-label>, aria-label, aria-labelledby or MatDatepickerIntl.

Always communicate the date format (e.g. 'MM/DD/YYYY'). This can be accomplished using <mat-hint> or by providing an additional label adjacent to the form field.

MatDatepickerInput adds >Alt + Down Arrow as a keyboard short to open the datepicker pop-up. However, ChromeOS intercepts this key combination at the OS level such that the browser only receives a PageDown key event. Because of this behavior, you should always include an additional means of opening the pop-up, such as MatDatepickerToggle.

MatDatepickerToggle must be included along with MatDatepicker for optimal mobile a11y compatibility. Mobile screen reader users currently do not have a way to trigger the datepicker dialog without the icon button present.

The datepicker supports the following keyboard shortcuts:

Keyboard Shortcut Action
Alt + Down Arrow Open the calendar pop-up
Escape Close the calendar pop-up

In month view:

Shortcut Action
Left Arrow Go to previous day
Right Arrow Go to next day
Up Arrow Go to same day in the previous week
Down Arrow Go to same day in the next week
Home Go to the first day of the month
End Go to the last day of the month
Page up Go to the same day in the previous month
Alt + Page up Go to the same day in the previous year
Page Down Go to the same day in the next month
Alt + Page Down Go to the same day in the next year
Enter Select current date

In year view:

Shortcut Action
Left Arrow Go to previous month
Right Arrow Go to next month
Up Arrow Go up a row (back 4 months)
Down Arrow Go down a row (forward 4 months)
Home Go to the first month of the year
End Go to the last month of the year
Page Up Go to the same month in the previous year
Alt + Page up Go to the same month 10 years back
Page Down Go to the same month in the next year
Alt + Page Down Go to the same month 10 years forward
Enter Select current month

In multi-year view:

Shortcut Action
Left Arrow Go to previous year
Right Arrow Go to next year
Up Arrow Go up a row (back 4 years)
Down Arrow Go down a row (forward 4 years)
Home Go to the first year in the current range
End Go to the last year in the current range
Page up Go back 24 years
Alt + Page up Go back 240 years
Page Down Go forward 24 years
Alt + Page Down Go forward 240 years
Enter Select current year

This error is thrown if you have not provided all of the injectables the datepicker needs to work. The easiest way to resolve this is to add provideNativeDateAdapter or provideMomentDateAdapter to your app config. See Choosing a date implementation) for more information.

This error is thrown if more than one <input> tries to claim ownership over the same <mat-datepicker> (via the matDatepicker attribute on the input). A datepicker can only be associated with a single input.

This error occurs if your <mat-datepicker> is not associated with any <input>. To associate an input with your datepicker, create a template reference for the datepicker and assign it to the matDatepicker attribute on the input:

<input [matDatepicker]="picker">
<mat-datepicker #picker></mat-datepicker>