@libs-ui/components-datetime-input
v0.2.356-1
Published
> **Version**: 0.2.355-15
Readme
Datetime Input Component
Version: 0.2.355-15
Component nhập giờ phút với hỗ trợ single time và time range, tự động format và validation.
Tính năng
- ✅ Single Time Input: Nhập giờ phút đơn giản (HH:mm)
- ✅ Time Range Input: Nhập khoảng thời gian (From - To)
- ✅ Auto Format: Tự động format thành HH:mm khi blur
- ✅ Auto Focus: Tự động chuyển focus giữa hours và minutes
- ✅ Validation: Hỗ trợ validation required và compare time
- ✅ Real-time Emit: Emit data real-time khi nhập
- ✅ Keyboard Support: Hỗ trợ đầy đủ keyboard navigation
- ✅ FunctionsControl: Điều khiển component từ bên ngoài
Khi nào sử dụng
- Khi cần nhập giờ phút đơn giản (HH:mm)
- Khi cần nhập khoảng thời gian (From - To)
- Khi cần validation cho time input (required, compare time)
- Khi cần so sánh thời gian bắt đầu và kết thúc
- Khi cần format time input tự động
- Khi cần emit data real-time trong quá trình nhập
Important Notes
⚠️ ISelectedMultiTime sử dụng WritableSignal — phải tạo bằng signal() khi truyền vào [selectedTime]
⚠️ Mặc định [ignoreAllowEqualTime]="true" — From và To bằng nhau sẽ bị coi là lỗi khi dùng isCheckErrorTimeEndGreaterTimeStart
⚠️ Auto Focus tự động chuyển focus: hours → minutes → toHours → toMinutes khi nhập đủ ký tự
⚠️ Component tự động format thành HH:mm khi blur (vd: nhập "9" → hiển thị "09")
⚠️ Validation chỉ chạy khi không ở trạng thái disable hoặc readonly
Installation
npm install @libs-ui/components-datetime-inputUsage
Basic Single Time
import { Component } from '@angular/core';
import { LibsUiComponentsDatetimeInputComponent, ISelectedTimeInput } from '@libs-ui/components-datetime-input';
@Component({
selector: 'app-example',
standalone: true,
imports: [LibsUiComponentsDatetimeInputComponent],
template: `
<libs_ui-components-datetime-input
[labelConfig]="{ labelLeft: 'Chọn giờ' }"
(outEmitSingleTime)="onTimeSelected($event)" />
`,
})
export class ExampleComponent {
onTimeSelected(event: ISelectedTimeInput) {
console.log('Time:', event); // { hours: 9, minute: 30 }
}
}Time Range
import { Component } from '@angular/core';
import { LibsUiComponentsDatetimeInputComponent, ISelectedMultiTime } from '@libs-ui/components-datetime-input';
@Component({
selector: 'app-example',
standalone: true,
imports: [LibsUiComponentsDatetimeInputComponent],
template: `
<libs_ui-components-datetime-input
[multiTime]="true"
[labelConfig]="{ labelLeft: 'Khoảng giờ' }"
(outEmitMultiTime)="onTimeRangeSelected($event)" />
`,
})
export class ExampleComponent {
onTimeRangeSelected(event: ISelectedMultiTime) {
console.log('From:', event.from?.());
console.log('To:', event.to?.());
}
}With Preset Value
import { Component, signal } from '@angular/core';
import { ISelectedMultiTime } from '@libs-ui/components-datetime-input';
@Component({
// ...
template: `
<libs_ui-components-datetime-input
[multiTime]="true"
[selectedTime]="selectedTime()"
[labelConfig]="{ labelLeft: 'Giờ làm việc' }"
(outEmitMultiTime)="onTimeRangeSelected($event)" />
`,
})
export class ExampleComponent {
// ⚠️ from và to PHẢI là WritableSignal
readonly selectedTime = signal<ISelectedMultiTime>({
from: signal({ hours: 9, minute: 30 }),
to: signal({ hours: 17, minute: 0 }),
});
onTimeRangeSelected(event: ISelectedMultiTime) {
console.log('Time range:', event);
}
}With Validation
import { Component } from '@angular/core';
@Component({
// ...
template: `
<libs_ui-components-datetime-input
[multiTime]="true"
[validRequired]="{ message: 'Vui lòng nhập giờ' }"
[validCompareTime]="{
message: 'Giờ kết thúc phải lớn hơn giờ bắt đầu',
isCheckErrorTimeEndGreaterTimeStart: true,
}"
(outEmitMultiTime)="onTimeRangeSelected($event)"
(outEmitValid)="onValidChange($event)" />
`,
})
export class ExampleComponent {
onTimeRangeSelected(event: ISelectedMultiTime) {
console.log('Time range:', event);
}
onValidChange(valid: { validRequired: boolean; validCompare: boolean }) {
console.log('Validation:', valid);
}
}FunctionsControl
import { Component, signal } from '@angular/core';
import { IDateTimeInputFunctionControlEvent } from '@libs-ui/components-datetime-input';
@Component({
// ...
template: `
<libs_ui-components-datetime-input
[multiTime]="true"
[validRequired]="{ message: 'Vui lòng nhập giờ' }"
(outFunctionsControl)="controls.set($event)"
/>
`,
})
export class ExampleComponent {
controls = signal<IDateTimeInputFunctionControlEvent | null>(null);
async validate() {
const isValid = await this.controls()?.checkIsValid();
console.log('Valid:', isValid);
}
async setError() {
await this.controls()?.setMessageError('Thời gian không hợp lệ');
}
async resetError() {
await this.controls()?.resetError();
}
}API
Inputs
| Property | Type | Default | Description |
| ---------------------------------------- | -------------------------------- | ----------------- | ------------------------------------------------------------------------------- |
| [classDatePickerInput] | string | undefined | CSS class cho date picker input |
| [classIncludeBetweenTime] | string | undefined | CSS class cho phần between time (dấu -) |
| [classIncludeInput] | string | libs-ui-font-h5r| CSS class cho input element |
| [defaultHeight] | number | 28 | Chiều cao mặc định của input (px) |
| [disable] | boolean | false | Disable input |
| [emitDataSingleDataWhenUseMultiTime] | boolean | false | Emit data riêng từng phần khi dùng multiTime |
| [fromAndToDateLabel] | { from?: string; to?: string } | undefined | Label cho From và To |
| [ignoreAllowEqualTime] | boolean | true | Khi true, From = To bị coi là lỗi (với isCheckErrorTimeEndGreaterTimeStart) |
| [ignoreBorder] | boolean | false | Ẩn border của input |
| [ignoreCheckValidWhenInput] | boolean | false | Bỏ qua validate khi nhập từ bàn phím |
| [ignoreMultiIcon] | boolean | false | Ẩn icon giữa 2 time range |
| [ignoreShowValid] | boolean | false | Ẩn hiển thị lỗi validation |
| [ignoreWithDefault] | boolean | false | Bỏ qua giá trị default |
| [isEmitRealTime] | boolean | false | Emit data real-time khi nhập (mỗi keystroke) |
| [labelConfig] | ILabel | undefined | Cấu hình label (labelLeft, required, ...) |
| [multiTime] | boolean | false | Chế độ chọn time range (From - To) |
| [readonly] | boolean | false | Readonly mode |
| [resetInput] | boolean | true | Cho phép reset input |
| [selectedTime] | ISelectedMultiTime | undefined | Giá trị time được set sẵn (sử dụng WritableSignal) |
| [showBorderError] | boolean | false | Hiển thị border error state |
| [validCompareTime] | IValidCompare | undefined | Cấu hình validation so sánh time |
| [validRequired] | IMessageTranslate | undefined | Cấu hình validation required |
Outputs
| Property | Type | Description |
| ----------------------- | --------------------------------------------------- | ------------------------------------------------------ |
| (outClickButtonLabel) | IButton | Event khi click button trên label |
| (outEmitMultiTime) | ISelectedMultiTime | Event khi chọn time range (cả from và to) |
| (outEmitRealTime) | ISelectedMultiTime | Event emit real-time khi nhập (mỗi keystroke) |
| (outEmitSingleTime) | ISelectedTimeInput | Event khi chọn single time |
| (outEmitValid) | { validRequired: boolean; validCompare: boolean } | Event trạng thái validation |
| (outFunctionsControl) | IDateTimeInputFunctionControlEvent | Emit functions để điều khiển component từ bên ngoài |
| (outLabelRightClick) | boolean | Event khi click label bên phải |
| (outResetTime) | ISelectedMultiTime \| undefined | Event khi reset time |
| (outSwitchEventLabel) | ISwitchEvent | Event khi switch trên label thay đổi |
FunctionsControl Methods
| Method | Description |
| ----------------------------- | -------------------------------------------------- |
| checkIsValid() | Kiểm tra validation và trả về Promise<boolean> |
| resetError(resetAll?) | Reset tất cả trạng thái lỗi |
| setMessageError(message) | Đặt message lỗi tùy chỉnh (undefined để xóa) |
Types
ISelectedTimeInput
export interface ISelectedTimeInput {
hours?: string | number;
minute?: string | number;
}ISelectedMultiTime
export interface ISelectedMultiTime {
from?: WritableSignal<ISelectedTimeInput>;
to?: WritableSignal<ISelectedTimeInput>;
}IValidCompare
export interface IValidCompare extends IMessageTranslate {
isCheckErrorTimeEndGreaterTimeStart?: boolean;
isCheckErrorTimeDuplicate?: boolean;
}IDateTimeInputFunctionControlEvent
export interface IDateTimeInputFunctionControlEvent {
checkIsValid: () => Promise<boolean>;
resetError: (resetAll?: boolean) => Promise<void>;
setMessageError: (message: string | undefined) => Promise<void>;
}Hidden Logic
Signal Auto-Unwrapping trong selectedTime
Khi truyền [selectedTime], component sử dụng effect() để watch thay đổi. Giá trị from/to là WritableSignal, component sẽ gọi .() để unwrap. Nếu truyền plain object thay vì signal sẽ gây lỗi.
Backspace Navigation
Khi nhấn Backspace ở ô trống, component tự động focus về ô trước đó (toMinutes → toHours → fromMinutes → fromHours). Cần nhấn Backspace 2 lần: lần 1 xóa giá trị, lần 2 chuyển focus.
Input Dependencies — ignoreCheckValidWhenInput
Khi [ignoreCheckValidWhenInput]="true", validation sẽ KHÔNG chạy ngay khi nhập từ bàn phím, chỉ chạy khi gọi checkIsValid() từ FunctionsControl.
Demo
Test
nx test components-datetime-inputLicense
MIT
