@libs-ui/components-datetime-picker
v0.2.357-3
Published
> Component chọn ngày tháng mạnh mẽ, hỗ trợ single date, date range, time picker, quick ranges và validation.
Readme
@libs-ui/components-datetime-picker
Component chọn ngày tháng mạnh mẽ, hỗ trợ single date, date range, time picker, quick ranges và validation.
Giới thiệu
LibsUiComponentsDatetimePickerComponent là một Angular Standalone Component cho phép người dùng chọn ngày tháng với nhiều chế độ linh hoạt: single date, date range, có hoặc không có time picker. Component tích hợp sẵn quick ranges (hôm nay, tuần này, tháng này...), custom ranges mở rộng, min/max date validation, required validation và hỗ trợ two-way binding qua Signal API.
Tính năng
- ✅ Single Date Picker — chọn một ngày duy nhất
- ✅ Date Range Picker — chọn khoảng thời gian từ - đến
- ✅ Time Picker tích hợp — bật/tắt linh hoạt qua
[hasTimePicker] - ✅ Quick Ranges — hôm nay, hôm qua, 7 ngày, 30 ngày, tháng này, tháng trước, 90 ngày
- ✅ Custom Ranges — mở rộng danh sách chọn nhanh qua
[extendRanges] - ✅ Auto Apply — tự động xác nhận khi người dùng chọn xong
- ✅ Min/Max Date — giới hạn ngày có thể chọn
- ✅ Required Validation — tích hợp kiểm tra bắt buộc nhập
- ✅ Function Control API —
checkIsValid(),reset(),resetError()qua(outFunctionsControl) - ✅ Two-way binding —
[(singleDateSelected)],[(dateRangeSelected)]qua Signal model - ✅ Label tích hợp — cấu hình label trái/phải qua
[labelConfig] - ✅ Localization — hỗ trợ đa ngôn ngữ Tiếng Việt / English
- ✅ Standalone + OnPush — hiệu năng tối ưu
Khi nào sử dụng
- Khi cần chọn một ngày cụ thể (form đơn, filter)
- Khi cần chọn khoảng thời gian để lọc dữ liệu (báo cáo, thống kê)
- Khi cần chọn cả ngày và giờ (đặt lịch, nhập thời gian)
- Khi cần quick ranges để người dùng chọn nhanh (dashboard filter)
- Khi cần validation bắt buộc nhập ngày trong form
Cài đặt
npm install @libs-ui/components-datetime-pickerImport
import { LibsUiComponentsDatetimePickerComponent } from '@libs-ui/components-datetime-picker';
// Interfaces & Types
import {
IEmitSingleDate,
IEmitDateRange,
IDateTimeValid,
IDateTimePickerFunctionControlEvent,
IDateRange,
LocalizationConfig,
} from '@libs-ui/components-datetime-picker';
// Define helpers
import {
getDateOptions,
getDateOptionsDefault,
getDateRangeDefault,
DEFAULT_MIN_YEAR,
DEFAULT_MAX_YEAR,
} from '@libs-ui/components-datetime-picker';Ví dụ sử dụng
1. Date Range Picker cơ bản (không có giờ)
import { Component } from '@angular/core';
import { LibsUiComponentsDatetimePickerComponent, IEmitDateRange } from '@libs-ui/components-datetime-picker';
@Component({
selector: 'app-filter',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Khoảng thời gian' }"
[widthByLabel]="false"
[isSingle]="false"
[hasTimePicker]="false"
(outSelectDateRange)="handlerSelectDateRange($event)"
/>
`,
})
export class FilterComponent {
handlerSelectDateRange(event: IEmitDateRange): void {
event.stopPropagation();
console.log('startDate:', event.startDate);
console.log('endDate:', event.endDate);
console.log('quickRangeId:', event.quickRangeId);
}
}2. Single Date Picker với giờ và giá trị mặc định
import { Component, signal } from '@angular/core';
import {
LibsUiComponentsDatetimePickerComponent,
IEmitSingleDate,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';
@Component({
selector: 'app-date-form',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Ngày thực hiện' }"
[widthByLabel]="false"
[isSingle]="true"
[hasTimePicker]="true"
[(singleDateSelected)]="selectedDate"
(outSelectSingleDate)="handlerSelectSingleDate($event)"
/>
`,
})
export class DateFormComponent {
readonly selectedDate = signal<IEmitSingleDate>({ date: getDayjs() });
handlerSelectSingleDate(event: IEmitSingleDate): void {
event.stopPropagation();
console.log('date:', event.date);
console.log('displayLabel:', event.displayLabel);
}
}3. Date Range với validation bắt buộc và Function Control
import { Component } from '@angular/core';
import {
LibsUiComponentsDatetimePickerComponent,
IEmitDateRange,
IDateTimePickerFunctionControlEvent,
} from '@libs-ui/components-datetime-picker';
@Component({
selector: 'app-report-filter',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Kỳ báo cáo' }"
[widthByLabel]="false"
[isSingle]="false"
[hasTimePicker]="false"
[validRequired]="{ message: 'Vui lòng chọn khoảng thời gian' }"
(outSelectDateRange)="handlerSelectDateRange($event)"
(outFunctionsControl)="handlerFunctionsControl($event)"
/>
<button (click)="handlerSubmit()">Tạo báo cáo</button>
`,
})
export class ReportFilterComponent {
private functionControl?: IDateTimePickerFunctionControlEvent;
handlerSelectDateRange(event: IEmitDateRange): void {
event.stopPropagation();
console.log('range:', event.startDate, '-', event.endDate);
}
handlerFunctionsControl(control: IDateTimePickerFunctionControlEvent): void {
this.functionControl = control;
}
async handlerSubmit(): Promise<void> {
const isValid = await this.functionControl?.checkIsValid();
if (!isValid) return;
// proceed with report generation
}
}4. Date Range với preset giá trị ban đầu (30 ngày qua)
import { Component, signal } from '@angular/core';
import {
LibsUiComponentsDatetimePickerComponent,
IEmitDateRange,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';
@Component({
selector: 'app-dashboard-filter',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Lọc theo ngày' }"
[widthByLabel]="false"
[isSingle]="false"
[hasTimePicker]="false"
[(dateRangeSelected)]="dateRange"
(outSelectDateRange)="handlerSelectDateRange($event)"
/>
`,
})
export class DashboardFilterComponent {
readonly dateRange = signal<IEmitDateRange>({
quickRangeId: '_30days_ago',
startDate: getDayjs().subtract(29, 'days').hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DDTHH:mm:ss[Z]'),
endDate: getDayjs().hour(23).minute(59).second(59).format('YYYY-MM-DDTHH:mm:ss[Z]'),
});
handlerSelectDateRange(event: IEmitDateRange): void {
event.stopPropagation();
console.log('selected range:', event);
}
}5. Date Range với Custom Ranges mở rộng
import { Component } from '@angular/core';
import {
LibsUiComponentsDatetimePickerComponent,
IEmitDateRange,
IDateRange,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';
@Component({
selector: 'app-custom-range',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Khoảng tùy chỉnh' }"
[widthByLabel]="false"
[isSingle]="false"
[hasTimePicker]="false"
[extendRanges]="customRanges"
(outSelectDateRange)="handlerSelectDateRange($event)"
/>
`,
})
export class CustomRangeComponent {
readonly customRanges: IDateRange[] = [
{
id: 'this_quarter',
label: 'Quý này',
values: [getDayjs().startOf('quarter'), getDayjs().endOf('quarter')],
},
{
id: 'last_quarter',
label: 'Quý trước',
values: [
getDayjs().subtract(1, 'quarter').startOf('quarter'),
getDayjs().subtract(1, 'quarter').endOf('quarter'),
],
},
];
handlerSelectDateRange(event: IEmitDateRange): void {
event.stopPropagation();
console.log('selected:', event);
}
}6. Single Date với Min/Max Date
import { Component } from '@angular/core';
import {
LibsUiComponentsDatetimePickerComponent,
IEmitSingleDate,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';
@Component({
selector: 'app-birth-date',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Ngày sinh' }"
[widthByLabel]="false"
[isSingle]="true"
[hasTimePicker]="false"
[minDate]="minDate"
[maxDate]="maxDate"
(outSelectSingleDate)="handlerSelectSingleDate($event)"
/>
`,
})
export class BirthDateComponent {
readonly minDate = getDayjs('1945-01-01');
readonly maxDate = getDayjs();
handlerSelectSingleDate(event: IEmitSingleDate): void {
event.stopPropagation();
console.log('birth date:', event.date);
}
}7. Auto Apply với reset
import { Component } from '@angular/core';
import {
LibsUiComponentsDatetimePickerComponent,
IEmitDateRange,
IEmitSingleDate,
IDateTimePickerFunctionControlEvent,
} from '@libs-ui/components-datetime-picker';
@Component({
selector: 'app-auto-filter',
standalone: true,
imports: [LibsUiComponentsDatetimePickerComponent],
template: `
<libs_ui-components-datetime-picker
[labelConfig]="{ labelLeft: 'Ngày tạo' }"
[widthByLabel]="false"
[isSingle]="false"
[hasTimePicker]="true"
[autoApply]="true"
[allowReset]="true"
(outSelectDateRange)="handlerSelectDateRange($event)"
(outReset)="handlerReset($event)"
(outFunctionsControl)="handlerFunctionsControl($event)"
/>
`,
})
export class AutoFilterComponent {
private functionControl?: IDateTimePickerFunctionControlEvent;
handlerSelectDateRange(event: IEmitDateRange): void {
event.stopPropagation();
console.log('range:', event);
}
handlerReset(event: IEmitDateRange | IEmitSingleDate | undefined): void {
event?.stopPropagation?.();
console.log('picker reset', event);
}
handlerFunctionsControl(control: IDateTimePickerFunctionControlEvent): void {
this.functionControl = control;
}
async handlerClearPicker(): Promise<void> {
await this.functionControl?.reset(false);
}
}@Input()
| Input | Type | Default | Mô tả | Ví dụ |
|---|---|---|---|---|
| [allowReset] | boolean | true | Hiển thị nút reset để xóa ngày đã chọn | [allowReset]="false" |
| [autoApply] | boolean | false | Tự động xác nhận ngay khi người dùng chọn đủ ngày (không cần nhấn Lưu) | [autoApply]="true" |
| [classInclude] | string | '' | CSS class thêm vào wrapper ngoài cùng của component | [classInclude]="'mt-4'" |
| [classIncludeCustomRanges] | string | '' | CSS class thêm vào vùng danh sách quick ranges | [classIncludeCustomRanges]="'w-[180px]'" |
| [classPickerContentInclude] | string | '' | CSS class thêm vào vùng nội dung popover bên trong | [classPickerContentInclude]="'p-2'" |
| [classPickerInclude] | string | '' | CSS class thêm vào trigger button hiển thị nhãn ngày | [classPickerInclude]="'w-full'" |
| [dateOptions] | LocalizationConfig | getDateOptionsDefault() | Cấu hình localization: tên tháng, ngày, nhãn nút, danh sách quick ranges | [dateOptions]="myConfig" |
| [(dateRangeSelected)] | IEmitDateRange | undefined | Two-way binding giá trị khoảng ngày đã chọn (dùng cho date range mode) | [(dateRangeSelected)]="dateRange" |
| [defaultWidth] | number | undefined | Ghi đè chiều rộng mặc định của trigger (px). Ưu tiên sau [widthByLabel]="false" | [defaultWidth]="300" |
| [directionPopover] | TYPE_POPOVER_DIRECTION | 'bottom' | Hướng mở của popover calendar | [directionPopover]="'top'" |
| [disable] | boolean | false | Vô hiệu hoá toàn bộ picker, không cho tương tác | [disable]="true" |
| [extendRanges] | Array<IDateRange> | [] | Danh sách quick ranges tuỳ chỉnh thêm vào ngoài danh sách mặc định | [extendRanges]="customRanges" |
| [flagMouse] | IFlagMouse (model) | { isMouseEnter: false, isMouseEnterContent: false } | Two-way binding trạng thái hover chuột (dùng khi tích hợp với popover cha) | [(flagMouse)]="flagMouse" |
| [hasTimePicker] | boolean | true | Hiển thị bộ chọn giờ/phút bên cạnh calendar | [hasTimePicker]="false" |
| [ignoreBorderQuickRange] | boolean | false | Ẩn viền ngăn cách giữa quick ranges và calendar | [ignoreBorderQuickRange]="true" |
| [ignoreStopPropagationEvent] | boolean | false | Bỏ qua stopPropagation trên sự kiện click (dùng khi component cha cần nhận event bubble) | [ignoreStopPropagationEvent]="true" |
| [isBorderError] | boolean | false | Hiển thị viền đỏ lỗi ngay lập tức mà không cần chạy validation | [isBorderError]="true" |
| [isNgContent] | boolean | false | Chế độ dùng ng-content thay thế trigger mặc định | [isNgContent]="true" |
| [isSingle] | boolean | false | Chuyển sang chế độ chọn single date (thay vì date range) | [isSingle]="true" |
| [labelConfig] | ILabel | undefined | Cấu hình label hiển thị bên trái hoặc bên phải picker | [labelConfig]="{ labelLeft: 'Ngày tạo' }" |
| [listYearHiddenInputSearch] | boolean | false | Ẩn ô tìm kiếm năm trong dropdown chọn năm | [listYearHiddenInputSearch]="true" |
| [maxDate] | Dayjs \| string | undefined | Ngày tối đa người dùng có thể chọn (ngày sau ngày này bị disabled) | [maxDate]="'2025-12-31'" |
| [minDate] | Dayjs \| string | undefined | Ngày tối thiểu người dùng có thể chọn (ngày trước ngày này bị disabled) | [minDate]="'2020-01-01'" |
| [placeholder] | string | undefined | Văn bản gợi ý hiển thị khi chưa chọn ngày | [placeholder]="'Chọn ngày'" |
| [positionQuickRanges] | 'left' \| 'right' | 'left' | Vị trí hiển thị danh sách quick ranges (trái hay phải so với calendar) | [positionQuickRanges]="'right'" |
| [rangesPopoverPosition] | 'start' \| 'center' \| 'end' | 'start' | Căn chỉnh ngang của popover so với trigger | [rangesPopoverPosition]="'end'" |
| [rangesPopoverPositionDistance] | number | 0 | Khoảng cách dịch chuyển ngang của popover (px) | [rangesPopoverPositionDistance]="8" |
| [readonly] | boolean | false | Chế độ chỉ đọc, không cho phép thay đổi ngày | [readonly]="true" |
| [(singleDateSelected)] | IEmitSingleDate | undefined | Two-way binding giá trị ngày đơn đã chọn (dùng cho single mode) | [(singleDateSelected)]="selectedDate" |
| [showCustomRangeLabel] | boolean | true | Hiển thị tuỳ chọn "Tuỳ Chỉnh" ở cuối danh sách quick ranges | [showCustomRangeLabel]="false" |
| [trackDateRageUpdateLabel] | boolean | false | Theo dõi reactive thay đổi dateRangeSelected để cập nhật label hiển thị | [trackDateRageUpdateLabel]="true" |
| [useColorModeExist] | boolean | false | Dùng màu sắc theo color mode hệ thống (dark/light theme) | [useColorModeExist]="true" |
| [validRequired] | IDateTimeValid | undefined | Cấu hình validation bắt buộc nhập. Khi không có giá trị và gọi checkIsValid() sẽ hiển thị lỗi | [validRequired]="{ message: 'Bắt buộc' }" |
| [widthByLabel] | boolean | true | Khi true: chiều rộng trigger co dãn theo label. Khi false: dùng chiều rộng cố định tự tính theo mode | [widthByLabel]="false" |
| [widthByParent] | boolean | false | Chiều rộng trigger theo 100% chiều rộng phần tử cha | [widthByParent]="true" |
| [zIndex] | number | 1200 | z-index của popover calendar | [zIndex]="1500" |
@Output()
| Output | Type | Mô tả | Handler TS | Binding HTML |
|---|---|---|---|---|
| (outChangStageFlagMouse) | IFlagMouse | Phát ra khi trạng thái hover chuột thay đổi (tích hợp với popover cha) | handlerChangStageFlagMouse(e: IFlagMouse): void { e.stopPropagation?.(); ... } | (outChangStageFlagMouse)="handlerChangStageFlagMouse($event)" |
| (outFunctionsControl) | IDateTimePickerFunctionControlEvent | Phát ra ngay khi component khởi tạo, cung cấp API kiểm soát: checkIsValid, reset, resetError | handlerFunctionsControl(e: IDateTimePickerFunctionControlEvent): void { this.funcCtrl = e; } | (outFunctionsControl)="handlerFunctionsControl($event)" |
| (outReset) | IEmitDateRange \| IEmitSingleDate \| undefined | Phát ra khi người dùng nhấn nút reset | handlerReset(e: IEmitDateRange \| IEmitSingleDate \| undefined): void { e?.stopPropagation?.(); ... } | (outReset)="handlerReset($event)" |
| (outSelectDateRange) | IEmitDateRange | Phát ra khi người dùng xác nhận chọn khoảng ngày (date range mode) | handlerSelectDateRange(e: IEmitDateRange): void { e.stopPropagation(); ... } | (outSelectDateRange)="handlerSelectDateRange($event)" |
| (outSelectSingleDate) | IEmitSingleDate | Phát ra khi người dùng xác nhận chọn một ngày (single mode) | handlerSelectSingleDate(e: IEmitSingleDate): void { e.stopPropagation(); ... } | (outSelectSingleDate)="handlerSelectSingleDate($event)" |
Function Control API
Nhận qua (outFunctionsControl) khi component khởi tạo. Dùng để tương tác chương trình với picker.
import { IDateTimePickerFunctionControlEvent } from '@libs-ui/components-datetime-picker';
export class MyComponent {
private functionControl?: IDateTimePickerFunctionControlEvent;
handlerFunctionsControl(control: IDateTimePickerFunctionControlEvent): void {
this.functionControl = control;
}
// Kiểm tra hợp lệ (hiển thị lỗi nếu validRequired được cấu hình và chưa chọn ngày)
async handlerValidate(): Promise<void> {
const isValid = await this.functionControl?.checkIsValid();
console.log('isValid:', isValid); // true | false
}
// Reset picker về trạng thái trống
async handlerClear(): Promise<void> {
await this.functionControl?.reset(false);
}
// Reset về giá trị cụ thể
async handlerResetToRange(): Promise<void> {
await this.functionControl?.reset(false, {
startDate: '2024-01-01',
endDate: '2024-01-31',
});
}
// Xóa thông báo lỗi đang hiển thị
async handlerClearError(): Promise<void> {
await this.functionControl?.resetError();
}
// Đặt thông báo lỗi tuỳ chỉnh
async handlerSetError(): Promise<void> {
await this.functionControl?.resetError('Ngày không hợp lệ với kỳ kế toán');
}
}| Method | Signature | Mô tả |
|---|---|---|
| checkIsValid | () => Promise<boolean> | Chạy validation, hiển thị lỗi nếu [validRequired] được cấu hình và chưa chọn ngày. Trả về true nếu hợp lệ |
| reset | (checkIsValid?: boolean, dateRangeReset?: IEmitDateRange, singleDateReset?: IEmitSingleDate) => Promise<void> | Reset picker. checkIsValid=true sẽ chạy lại validation sau reset. Có thể truyền giá trị để reset về ngày cụ thể |
| resetError | (message?: string, interpolateParams?: TYPE_OBJECT) => Promise<void> | Xóa hoặc đặt lại thông báo lỗi. Gọi không tham số để xóa lỗi |
Types & Interfaces
import {
IEmitSingleDate,
IEmitDateRange,
IDateTimeValid,
IDateTimePickerFunctionControlEvent,
IDateRange,
LocalizationConfig,
TYPE_RANGE_KEY,
} from '@libs-ui/components-datetime-picker';IEmitSingleDate
Dữ liệu trả về khi chọn single date.
export interface IEmitSingleDate {
displayLabel?: string; // Chuỗi hiển thị trên trigger (VD: "15/06/2024 09:30")
date: string | Dayjs | undefined; // Giá trị ngày đã chọn
values?: {
month: string | number;
year: string | number;
day: string | number;
hour?: string | number;
minute?: string | number;
};
}IEmitDateRange
Dữ liệu trả về khi chọn date range.
export interface IEmitDateRange {
quickRangeId?: string; // ID của quick range đã chọn (VD: 'today', '_7days_ago', 'this_month')
displayLabel?: string; // Chuỗi hiển thị (VD: "01/06/2024 - 30/06/2024")
startDate: string | Dayjs | undefined;
endDate: string | Dayjs | undefined;
}IDateTimeValid
Cấu hình validation bắt buộc nhập.
export interface IDateTimeValid {
message?: string; // Thông báo lỗi tuỳ chỉnh (hỗ trợ i18n key)
interpolateParams?: Record<string, any>; // Tham số nội suy cho i18n
ignoreMessage?: boolean; // Ẩn văn bản lỗi, chỉ hiện viền đỏ
}IDateTimePickerFunctionControlEvent
API kiểm soát picker từ bên ngoài, nhận qua (outFunctionsControl).
export interface IDateTimePickerFunctionControlEvent {
checkIsValid: () => Promise<boolean>;
resetError: (message?: string, interpolateParams?: TYPE_OBJECT) => Promise<void>;
reset: (
checkIsValid?: boolean,
dateRangeSelected?: IEmitDateRange,
singleDateReset?: IEmitSingleDate
) => Promise<void>;
}IDateRange
Cấu trúc một mục custom range trong [extendRanges].
export interface IDateRange {
id: string; // ID duy nhất, sẽ được trả về trong IEmitDateRange.quickRangeId
label: string; // Nhãn hiển thị trong danh sách quick ranges
values?: Array<Dayjs>; // [startDate, endDate] - nếu không truyền, sẽ hiển thị như "Custom Range"
}LocalizationConfig
Cấu hình ngôn ngữ và danh sách quick ranges mặc định.
export interface LocalizationConfig {
monthNames: string[]; // 12 tên tháng
ranges: { [key: string]: string }; // Map ID quick range → nhãn hiển thị
daysOfWeek: string[]; // 7 tên ngày trong tuần
applyLabel: string; // Nhãn nút xác nhận
cancelLabel: string; // Nhãn nút huỷ
fromLabel: string; // Nhãn "Từ"
toLabel: string; // Nhãn "Đến"
customRangeLabel: string; // Nhãn tùy chọn "Tuỳ Chỉnh"
format?: string;
direction?: string;
separator?: string;
weekLabel?: string;
clearLabel?: string;
firstDay?: number; // Ngày đầu tuần (0 = CN, 1 = T2)
displayFormat?: string;
}TYPE_RANGE_KEY
Danh sách ID quick range mặc định của hệ thống.
export type TYPE_RANGE_KEY =
| 'today'
| 'yesterday'
| '_7days_ago'
| '_30days_ago'
| 'this_month'
| 'last_month'
| '_3months_ago';Defines & Helpers
import {
getDateOptions,
getDateOptionsDefault,
getDateRangeDefault,
defaultLocaleConfig,
DEFAULT_MIN_YEAR,
DEFAULT_MAX_YEAR,
} from '@libs-ui/components-datetime-picker';
// Lấy LocalizationConfig theo ngôn ngữ hiện tại (VI/EN)
const config = getDateOptions();
// Lấy LocalizationConfig đầy đủ với defaultLocaleConfig merge vào
const fullConfig = getDateOptionsDefault();
// Lấy object mapping ID quick range → [startDayjs, endDayjs]
const ranges = getDateRangeDefault();
// ranges.today → [startOfDay, endOfDay]
// ranges._7days_ago → [6 ngày trước 00:00, hôm nay 23:59]
// Năm tối thiểu/tối đa mặc định
console.log(DEFAULT_MIN_YEAR); // 1945
console.log(DEFAULT_MAX_YEAR); // năm hiện tại + 5Lưu ý quan trọng
⚠️ isSingle vs isSingle=false: Khi [isSingle]="true", lắng nghe (outSelectSingleDate) và dùng [(singleDateSelected)]. Khi [isSingle]="false" (mặc định), lắng nghe (outSelectDateRange) và dùng [(dateRangeSelected)]. Trộn lẫn hai mode sẽ không hiển thị giá trị đúng.
⚠️ hasTimePicker mặc định là true: Nếu không cần giờ phút, hãy truyền rõ [hasTimePicker]="false". Khi true, format hiển thị là DD/MM/YYYY HH:mm; khi false là DD/MM/YYYY.
⚠️ outFunctionsControl emit khi ngOnInit: (outFunctionsControl) chỉ phát ra một lần duy nhất khi component khởi tạo. Luôn lưu giá trị nhận được vào biến class để dùng sau.
⚠️ Preset giá trị ban đầu: Khi truyền [dateRangeSelected] hoặc [singleDateSelected] với quickRangeId, đảm bảo quickRangeId trùng khớp với key trong dateOptions.ranges. Nếu không khớp, nhãn hiển thị sẽ tính lại từ startDate/endDate.
⚠️ trackDateRageUpdateLabel: Mặc định false — label chỉ cập nhật khi người dùng tương tác. Đặt [trackDateRageUpdateLabel]="true" nếu cần label cập nhật reactive khi dateRangeSelected thay đổi từ bên ngoài (ví dụ: reset programmatic).
⚠️ Format ngày truyền vào: minDate, maxDate, startDate, endDate chấp nhận cả Dayjs object lẫn string ISO (VD: '2024-06-15', '2024-06-15T00:00:00Z'). Khuyến nghị dùng getDayjs() từ @libs-ui/utils để đảm bảo timezone nhất quán.
⚠️ widthByLabel mặc định là true: Khi true, chiều rộng trigger tự co dãn theo nội dung label ngày. Để có chiều rộng cố định đẹp hơn trong form, đặt [widthByLabel]="false". Chiều rộng tự tính lúc đó: range+time=322px, range=232px, single+time=190px, single=152px.
Demo
npx nx serve core-uiTruy cập: http://localhost:4500/components/datetime/picker
