Create consistent cross-browser and cross-device Angular time picker.
Available in Other JavaScript Frameworks
CoreUI Angular Time Picker Component is also available for Bootstrap, React, and Vue. Explore framework-specific implementations below:
Examples
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-example',
templateUrl: './time-picker-example.component.html',
standalone: true,
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerExampleComponent {
time? = new Date();
}<c-row>
<c-col lg="4">
<c-time-picker />
</c-col>
<c-col lg="4">
<c-time-picker [time]="time" />
</c-col>
</c-row>Sizing
Set heights using size property like size="lg" and size="sm".
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-sizing',
templateUrl: './time-picker-sizing.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerSizingComponent {}<c-row class="mb-4">
<c-col lg="5">
<c-time-picker size="lg" />
</c-col>
</c-row>
<c-row>
<c-col lg="4">
<c-time-picker size="sm" />
</c-col>
</c-row>
Disabled
Add the disabled boolean attribute on an input to give it a grayed out appearance and remove pointer events. Disabling the picker also closes its open menu.
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-disabled',
templateUrl: './time-picker-disabled.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerDisabledComponent {
time? = new Date();
}<c-row>
<c-col lg="4">
<c-time-picker disabled />
</c-col>
<c-col lg="4">
<c-time-picker disabled [time]="time" />
</c-col>
</c-row>Typing a time
The input reads a time typed the way the picker shows it in its locale, with the locale’s digits and day periods (9:05 PM, 오후 9:05, ۲۱:۰۵), as well as 24-hour time (21:05), a dot as the separator (21.05) and AM/PM in any letter case. A time without a day period is read as 24-hour time. The time is read when the input changes (Enter or leaving the input) and on ArrowDown or Alt + ArrowDown, each part snaps to the nearest value allowed by its filter, and seconds are kept only with seconds. Text that is not a time clears the picker. Picking a value in the menu before the typed text is read replaces that text with the picked time.
A string bound to time or written by a form control is read the same way, along with ISO times and date-times (15:30:00, 2026-01-05T15:30:00, 2026-01-05 15:30:00). A string in the locale’s own format is read with the picker’s locale, also when the locale arrives later; a time already read, picked or cleared stays when only locale changes.
The picker reports a Date. A time without a date, from a time string or picked or typed into an empty picker, is set on 1 January 1970; a time string with a UTC offset (15:30Z, 15:30+02:00) is that moment on 1 January 1970, so its local date can be a day earlier or later. A picked or typed time keeps the date of the time it replaces. A Date bound to time or written by a form control keeps its moment, also when it comes from another window or frame, and so does a date-time string (2026-01-05T15:30:00). To store or send a time without a date, use its hours, minutes and, with seconds, seconds rather than toISOString(): the UTC offset of 1 January 1970 can differ from today’s.
Readonly
Add the inputReadOnly boolean attribute to prevent modification of the input value.
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-readonly',
templateUrl: './time-picker-readonly.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerReadonlyComponent {}<c-row>
<c-col lg="4">
<c-time-picker inputReadOnly />
</c-col>
</c-row>Validation
Set valid to show the validation state. [valid]="false" also sets aria-invalid="true" on the input or, in the select variant, on every select. aria-describedby on c-time-picker, as a static attribute or bound with [aria-describedby], moves to the same fields, so the feedback is read with them; [attr.aria-describedby] does not reach the fields.
import { Component } from '@angular/core';
import { ColComponent, FormFeedbackComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-validation',
templateUrl: './time-picker-validation.component.html',
imports: [ColComponent, FormFeedbackComponent, RowComponent, TimePickerComponent]
})
export class TimePickerValidationComponent {}<c-row>
<c-col lg="4">
<c-time-picker [valid]="false" aria-describedby="timePickerFeedback" />
<c-form-feedback id="timePickerFeedback" [valid]="false">Choose a time.</c-form-feedback>
</c-col>
</c-row>Filtered
Add filter callback functions to limit selectable values. The first choice in an empty picker fills the parts not picked yet with their first allowed values (seconds stay 0 without seconds), so it reports one time. In a 12-hour locale an empty picker shows the day period of the first allowed hour, a day period without allowed hours is disabled, and switching the day period keeps the hour 12 hours apart when it is allowed, otherwise it takes the first allowed hour of that day period.
import { DatePipe } from '@angular/common';
import { Component, signal } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-filtered',
templateUrl: './time-picker-filtered.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent, DatePipe]
})
export class TimePickerFilteredComponent {
filterHours = (hour: number): boolean => hour > 8 && hour <= 23;
filterMinutes = (min: number): boolean => (min %= 10) === 0;
filterSeconds = (sec: number): boolean => (sec %= 15) === 0;
readonly time = signal<Date | undefined>(new Date(1970, 0, 1, 14, 30, 15));
handleTimeChange(time: Date | undefined) {
if (time) {
this.time.set(new Date(time?.getTime()));
} else {
this.time.set(time);
}
}
}<c-row>
<c-col lg="4">
<c-time-picker
(timeChange)="handleTimeChange($event)"
[filterHours]="filterHours"
[filterMinutes]="filterMinutes"
[filterSeconds]="filterSeconds"
[(time)]="time"
seconds
/>
</c-col>
<c-col class="d-flex align-items-center">
{{time() | date:'shortTime'}}
</c-col>
</c-row>with Footer
import { Component, signal } from '@angular/core';
import {
ButtonDirective,
ColComponent,
DropdownCloseDirective,
RowComponent,
TemplateIdDirective,
TimePickerComponent
} from '@coreui/angular';
@Component({
selector: 'docs-time-picker-with-footer',
templateUrl: './time-picker-with-footer.component.html',
imports: [
RowComponent,
ColComponent,
TimePickerComponent,
TemplateIdDirective,
ButtonDirective,
DropdownCloseDirective
]
})
export class TimePickerWithFooterComponent {
readonly time = signal(new Date());
}<c-row>
<c-col lg="4">
<c-time-picker
[(time)]="time"
placeholder="-- : --"
#timePicker="cTimePicker"
>
<ng-template cTemplateId="timePickerFooter" let-dropdown>
<button cButton color="secondary" variant="ghost" size="sm"
(click)="timePicker.clearTime()" cDropdownClose
[dropdownComponent]="dropdown">
Cancel
</button>
<button cButton color="primary" size="sm" [disabled]="!time()" cDropdownClose [dropdownComponent]="dropdown">OK</button>
</ng-template>
</c-time-picker>
</c-col>
</c-row>Non-english locale
Auto
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-auto',
templateUrl: './time-picker-auto.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerAutoComponent {}<c-row>
<c-col lg="4">
<c-time-picker />
</c-col>
</c-row>Chinese
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-chinese',
templateUrl: './time-picker-chinese.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerChineseComponent {}<c-row>
<c-col lg="4">
<c-time-picker placeholder="入住日期" locale="zh-CN" seconds />
</c-col>
</c-row>Japanese
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-japanese',
templateUrl: './time-picker-japanese.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerJapaneseComponent {}<c-row>
<c-col lg="4">
<c-time-picker placeholder="日付を選択" locale="ja" seconds />
</c-col>
</c-row>Korean
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-korean',
templateUrl: './time-picker-korean.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerKoreanComponent {}<c-row>
<c-col lg="4">
<c-time-picker placeholder="날짜 선택" locale="ko" />
</c-col>
</c-row>Hebrew
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-hebrew',
templateUrl: './time-picker-hebrew.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerHebrewComponent {}<c-row>
<c-col lg="4">
<c-time-picker placeholder="בחר תאריך" locale="he-IL" />
</c-col>
</c-row>Persian
import { Component } from '@angular/core';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-persian',
templateUrl: './time-picker-persian.component.html',
imports: [RowComponent, ColComponent, TimePickerComponent]
})
export class TimePickerPersianComponent {}<c-row>
<c-col lg="4">
<c-time-picker placeholder="تاریخ شروع" locale="fa-IR" seconds />
</c-col>
</c-row>
Accessibility
- The input is a combobox that opens a dialog with the time selection: it has
aria-haspopup="dialog",aria-expanded, andaria-controlspointing to the open menu, named byariaPopupLabel(Time selection). Added in v5.7.41 - The roll columns are named by
ariaSelectHoursLabel,ariaSelectMinutesLabel,ariaSelectSecondsLabelandariaSelectMeridiemLabel(Select hours,Select minutes,Select seconds,Select AM/PM), and their values are options witharia-selected, named with the value and the column name (07, Select hours), so a screen reader says the unit when the focus moves between columns. The selects of theselectvariant get the same names, which take the place of a<label>wrapping the picker, so a picker with a visible label needs that label in these names, e.g.ariaSelectHoursLabel="Start time, hours". Added in v5.7.41 - On a right-to-left page the columns read AM/PM, hours, minutes, seconds from the left, the way the time is written, and the arrow keys follow that order. Added in v5.7.41
- Closing the menu after using it (
Escape, a button in the footer, a click outside) returns focus to the input. After a tap or a pen press in the menu an editable input does not get it back; a read-only input (inputReadOnly) does.
Keyboard behavior
| Key | Action |
|---|---|
ArrowDown or Alt + ArrowDown (Option on macOS) in the input | Read the typed text as leaving the input does, open the menu and move focus to the selected hour, or the first hour when none is selected Added in v5.7.41 |
Tab / Shift + Tab | Move between the input and the columns, landing on each column’s selected value, or its first value when none is selected; a time typed in the input is read first; tabbing out of the picker closes the menu |
ArrowDown / ArrowUp on a value | Move to the next or previous value in the column |
Home / End on a value | Move to the first or last value in the column Added in v5.7.41 |
ArrowLeft / ArrowRight on a value | Move to the column on that side Added in v5.7.41 |
Enter / Space on a value | Pick it. Then the focus moves to the next column in the order hours, minutes, seconds, AM/PM, and stays in the last one Added in v5.7.41 |
Escape | Close the menu, focus the input |
Forms
Angular handles user input through reactive and template-driven forms. CoreUI Time Picker supports both types.
The picker updates its form control and emits timeChange once when the user changes the time or the page calls clearTime(). With the default updateOn: 'change', a correction made in valueChanges is kept and is the time timeChange carries. Binding time or writing the form control updates the picker without either. A bound or written time that the filters or seconds do not allow is shown at the nearest allowed value, while the binding and the form keep the value they set until the user picks a time.
Reactive
import { JsonPipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
interface ITimePickerForm {
timePicker: FormControl<Date | undefined | null>;
}
@Component({
selector: 'docs-time-picker-reactive',
templateUrl: './time-picker-reactive.component.html',
imports: [RowComponent, ColComponent, ReactiveFormsModule, TimePickerComponent, JsonPipe]
})
export class TimePickerReactiveComponent implements OnInit {
time = new Date();
formGroup!: FormGroup<ITimePickerForm>;
get toLocaleTimeString() {
return this.formGroup.value.timePicker ? this.formGroup.value.timePicker.toLocaleTimeString() : '';
}
ngOnInit(): void {
this.time.setMilliseconds(0);
this.time.setSeconds(0);
this.time.setMinutes(15);
this.time.setHours(11);
this.formGroup = new FormGroup<ITimePickerForm>({
timePicker: new FormControl(this.time, { nonNullable: false })
});
}
}<c-row>
<c-col lg="4">
<form [formGroup]="formGroup">
<c-time-picker formControlName="timePicker" seconds />
</form>
</c-col>
</c-row>
<br>
Form value: {{formGroup.value | json }}
<br>
timePicker value: {{toLocaleTimeString}}Template-driven
import { DatePipe, JsonPipe } from '@angular/common';
import { Component, OnInit, signal } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ColComponent, RowComponent, TimePickerComponent } from '@coreui/angular';
@Component({
selector: 'docs-time-picker-template-driven',
templateUrl: './time-picker-template-driven.component.html',
imports: [RowComponent, ColComponent, ReactiveFormsModule, FormsModule, TimePickerComponent, JsonPipe, DatePipe]
})
export class TimePickerTemplateDrivenComponent implements OnInit {
readonly time = signal(new Date());
ngOnInit(): void {
const time = this.time();
time.setMilliseconds(0);
time.setSeconds(0);
time.setMinutes(15);
time.setHours(13);
this.time.set(time);
}
}<c-row>
<c-col lg="4">
<form #form="ngForm">
<c-time-picker [(ngModel)]="time" name="timePicker" />
</form>
</c-col>
</c-row>
<br>
Form value: {{ form.value | json }}
<br>
timePicker value: {{ form.value['timePicker'] | date:'H:mm'}}API reference
TimePicker Module
import {
TimePickerModule,
DropdownModule,
SharedModule
} from '@coreui/angular';
@NgModule({
imports: [
TimePickerModule,
DropdownModule,
SharedModule
]
})
export class AppModule() { }c-time-picker
component
import { TimePickerComponent } from '@coreui/angular-pro'