Datetime Dropdown
Component chọn ngày/tháng/năm/quý dạng dropdown, hỗ trợ single và multi (from-to) selection với validation tự động.
Version
0.2.355-14
Khi nào sử dụng
- Cần chọn tháng/năm/quý từ dropdown thay vì calendar picker
- Cần chọn khoảng thời gian (from-to) với validation tự động
- Cần tùy chỉnh format hiển thị (
year, month, quarter, year-month, month-day, year-quarter)
- Cần responsive layout tự động cho form nhỏ
Important Notes
selectedDateTime sử dụng WritableSignal — cần tạo signal trước khi truyền vào
typeFormat quyết định số lượng và loại dropdown hiển thị
isMultiple=true sẽ hiển thị 2 nhóm dropdown (From/To) với validation so sánh
- Component tự động responsive khi không đủ không gian
Cài đặt & Import
import {
LibsUiComponentsDatetimeDropdownComponent,
IEmitSingleDateDropdown,
IEmitMultiDateDropdown,
IDateDropdownFunctionControlEvent,
TYPE_DATE_DROPDOWN_FORMAT,
IFromAndToDateLabel,
IValidDateDropdown,
} from '@libs-ui/components-datetime-dropdown';
Ví dụ sử dụng
1. Basic Usage (month-day single)
<libs_ui-components-datetime-dropdown
[typeFormat]="'month-day'"
(outChooseSingleDate)="onSingleDateSelected($event)"
></libs_ui-components-datetime-dropdown>
import { signal } from '@angular/core';
import { IEmitSingleDateDropdown } from '@libs-ui/components-datetime-dropdown';
onSingleDateSelected(event: IEmitSingleDateDropdown) {
console.log('Month:', event.month, 'Day:', event.day);
}
2. Different Formats
<libs_ui-components-datetime-dropdown
[typeFormat]="'year'"
[reverseYear]="true"
[minYear]="2020"
[maxYear]="2030"
(outChooseSingleDate)="onYearSelected($event)"
></libs_ui-components-datetime-dropdown>
<libs_ui-components-datetime-dropdown
[typeFormat]="'month'"
(outChooseSingleDate)="onMonthSelected($event)"
></libs_ui-components-datetime-dropdown>
<libs_ui-components-datetime-dropdown
[typeFormat]="'year-month'"
(outChooseSingleDate)="onYearMonthSelected($event)"
></libs_ui-components-datetime-dropdown>
<libs_ui-components-datetime-dropdown
[typeFormat]="'year-quarter'"
(outChooseSingleDate)="onYearQuarterSelected($event)"
></libs_ui-components-datetime-dropdown>
3. Multi Date Range (from-to)
<libs_ui-components-datetime-dropdown
[typeFormat]="'year-month'"
[isMultiple]="true"
[fromAndToDateLabel]="{ from: 'i18n_label_from', to: 'i18n_to' }"
[selectedDateTime]="selectedRange"
(outChooseMultiDate)="onMultiDateSelected($event)"
(outFunctionsControl)="onFunctionsControl($event)"
></libs_ui-components-datetime-dropdown>
import { signal, WritableSignal } from '@angular/core';
import {
IEmitMultiDateDropdown,
IEmitSingleDateDropdown,
IDateDropdownFunctionControlEvent,
} from '@libs-ui/components-datetime-dropdown';
selectedRange: IEmitMultiDateDropdown = {
from: signal<IEmitSingleDateDropdown>({ year: 2024, month: 1 }),
to: signal<IEmitSingleDateDropdown>({ year: 2024, month: 12 }),
};
functionsControl!: IDateDropdownFunctionControlEvent;
onMultiDateSelected(event: IEmitMultiDateDropdown) {
console.log('From:', event.from(), 'To:', event.to());
}
onFunctionsControl(event: IDateDropdownFunctionControlEvent) {
this.functionsControl = event;
}
4. With Validation
<libs_ui-components-datetime-dropdown
[typeFormat]="'year-month'"
[isMultiple]="true"
[validRequired]="{ message: 'i18n_required', messageValidCompareTime: 'i18n_invalid_range' }"
[ignoreAllowTimeEqual]="true"
[ignoreValidTimeCompare]="false"
[isCheckErrorWhenSelectItem]="true"
[isBorderError]="isBorderError"
(outFunctionsControl)="onFunctionsControl($event)"
(outChooseMultiDate)="onMultiDateSelected($event)"
></libs_ui-components-datetime-dropdown>
async onSubmit() {
const isValid = await this.functionsControl.checkIsValid();
if (!isValid) {
return;
}
}
resetForm() {
this.functionsControl.resetTime?.();
this.functionsControl.resetError?.();
}
API Reference
Inputs
[classIncludeTextDisplayWhenNoSelect] | string | undefined | undefined | CSS class tùy chỉnh text hiển thị khi chưa chọn giá trị |
[disable] | boolean | false | Vô hiệu hóa toàn bộ component |
[disableSecond] | boolean | false | Vô hiệu hóa dropdown thứ hai cho đến khi dropdown đầu tiên được chọn |
[fromAndToDateLabel] | IFromAndToDateLabel | { from: 'i18n_label_from', to: 'i18n_to' } | Tùy chỉnh label From/To khi isMultiple=true |
[getItemYearDisplay] | (year: string) => string | — | Hàm tùy chỉnh hiển thị label cho item năm |
[hiddenDate] | IHiddenDate | undefined | undefined | Ẩn các giá trị ngày/tháng cụ thể khỏi dropdown |
[ignoreAllowTimeEqual] | boolean | true | Bỏ qua cho phép thời gian bằng nhau khi so sánh from/to. true = from phải nhỏ hơn to (không cho bằng) |
[ignoreConvertYearSelected] | boolean | false | Bỏ qua chuyển đổi label năm đã chọn (hiển thị raw value) |
[ignoreFromAndToDateLabel] | boolean | false | Ẩn label From/To khi isMultiple=true |
[ignoreRequiredValueSecondWhenNotValidRequired] | boolean | false | Bỏ qua validate giá trị thứ 2 khi validRequired không được set |
[ignoreValidTimeCompare] | boolean | false | Bỏ qua validation so sánh thời gian from/to |
[isBorderError] | boolean | false | Hiển thị viền lỗi trên component |
[isCheckErrorWhenSelectItem] | boolean | true | Kiểm tra lỗi mỗi khi chọn item |
[isEmitAfterChanged] | boolean | false | Emit outSelectedDropdown mỗi lần chọn giá trị (bao gồm lần đầu init) |
[isMultiple] | boolean | false | Chế độ multi selection (From/To) — hiển thị 2 nhóm dropdown |
[labelConfig] | ILabel | undefined | undefined | Cấu hình label (từ @libs-ui/components-label) |
[listHasButtonUnSelectOption] | boolean | false | Hiển thị nút bỏ chọn trong dropdown list |
[listKeysDisable] | IDateDropdownDisableKeys | undefined | undefined | Danh sách key bị vô hiệu hóa cho từng dropdown (from/to) |
[listMaxItemShow] | { year?: number; month?: number; quarter?: number; day?: number } | undefined | undefined | Giới hạn số item hiển thị cho từng loại dropdown |
[maxYear] | number | 0 (sử dụng DEFAULT_MAX_YEAR) | Năm tối đa hiển thị trong dropdown năm |
[minWidth] | number | undefined | undefined | Chiều rộng tối thiểu của component (px) |
[minYear] | number | 0 (sử dụng DEFAULT_MIN_YEAR) | Năm tối thiểu hiển thị trong dropdown năm |
[readonly] | boolean | false | Chế độ chỉ đọc |
[reverseYear] | boolean | undefined | undefined | Đảo ngược thứ tự danh sách năm (năm mới nhất lên đầu) |
[selectedDateTime] | IEmitMultiDateDropdown | undefined | undefined | Giá trị khởi tạo — sử dụng WritableSignal bên trong |
[typeFormat] | TYPE_DATE_DROPDOWN_FORMAT | 'month-day' | Loại format hiển thị: 'year', 'month', 'quarter', 'year-month', 'month-day', 'year-quarter' |
[validRequired] | IValidDateDropdown | — | Cấu hình validation bắt buộc với message lỗi tùy chỉnh |
[widthByElement] | boolean | false | Tính width dropdown theo phần tử cha |
[widthDropdown] | number | 136 | Chiều rộng mỗi dropdown (px) |
[zIndex] | number | 1200 | z-index của dropdown overlay |
Outputs
(outChangStageFlagMouse) | EventEmitter<IFlagMouse> | Emit khi trạng thái chuột thay đổi (hover/leave) |
(outChooseMultiDate) | EventEmitter<IEmitMultiDateDropdown> | Emit khi chọn đầy đủ cả From và To (chỉ khi isMultiple=true) |
(outChooseSingleDate) | EventEmitter<IEmitSingleDateDropdown> | Emit khi chọn đầy đủ single date (chỉ khi isMultiple=false) |
(outFunctionsControl) | EventEmitter<IDateDropdownFunctionControlEvent> | Emit object chứa các hàm điều khiển component từ bên ngoài |
(outSelectedDropdown) | EventEmitter<IEmitSingleDateDropdown | IEmitMultiDateDropdown> | Emit mỗi lần chọn giá trị (cần isEmitAfterChanged=true). Lưu ý: cần check undefined kỹ khi sử dụng |
FunctionsControl Methods
Object nhận được từ (outFunctionsControl):
checkIsValid() | Promise<boolean> | Kiểm tra validation toàn bộ component. Trả về false nếu có lỗi required hoặc lỗi so sánh from/to |
resetError() | Promise<void> | Xóa tất cả trạng thái lỗi hiển thị trên component |
resetTime() | Promise<void> | Reset toàn bộ giá trị đã chọn về trạng thái ban đầu |
Types & Interfaces
TYPE_DATE_DROPDOWN_FORMAT
type TYPE_DATE_DROPDOWN_FORMAT = 'year' | 'month' | 'quarter' | 'year-month' | 'month-day' | 'year-quarter' | string;
TYPE_DATE_FORMAT
type TYPE_DATE_FORMAT = 'year' | 'month' | 'quarter' | 'day';
IEmitSingleDateDropdown
interface IEmitSingleDateDropdown {
year?: number;
month?: number;
quarter?: number;
day?: number;
}
IEmitMultiDateDropdown
interface IEmitMultiDateDropdown {
from: WritableSignal<IEmitSingleDateDropdown>;
to: WritableSignal<IEmitSingleDateDropdown>;
}
IDateDropdownFunctionControlEvent
interface IDateDropdownFunctionControlEvent {
checkIsValid: () => Promise<boolean>;
resetError?: () => Promise<void>;
resetTime?: () => Promise<void>;
}
IValidDateDropdown
interface IValidDateDropdown {
message?: string;
interpolateParams?: { any: object };
messageValidCompareTime?: string;
interpolateParamsCompareTime?: { any: object };
}
IFromAndToDateLabel
interface IFromAndToDateLabel {
to?: string;
from?: string;
classLabelTo?: string;
classLabelFrom?: string;
}
IDateDropdownDisableKeys
interface IDateDropdownDisableKeys {
from?: WritableSignal<IDateDropdownDisable>;
to?: WritableSignal<IDateDropdownDisable>;
}
interface IDateDropdownDisable {
year?: WritableSignal<Array<number>>;
month?: WritableSignal<Array<number>>;
quarter?: WritableSignal<Array<number>>;
day?: WritableSignal<Array<number>>;
}
IHiddenDate
interface IHiddenDate {
formatDate: TYPE_DATE_DROPDOWN_FORMAT;
yearMonth?: WritableSignal<Array<WritableSignal<{ hiddenYear: number; hiddenMonths: Array<number> }>>>;
monthDay?: WritableSignal<Array<WritableSignal<{ hiddenMonth: number; hiddenDays: Array<number> }>>>;
}
Tùy chỉnh style
- Sử dụng
[classIncludeTextDisplayWhenNoSelect] để tùy chỉnh text display khi chưa chọn giá trị
- Sử dụng
[widthDropdown] để điều chỉnh chiều rộng mỗi dropdown (mặc định 136px)
- Sử dụng
[fromAndToDateLabel] để tùy chỉnh label From/To, bao gồm cả CSS class qua classLabelFrom và classLabelTo
Demo
Test
npx nx test components-datetime-dropdown