npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-datetime-dropdown

v0.2.357-5

Published

> Component dropdown chọn ngày tháng theo từng phần (năm, tháng, quý, ngày) với hỗ trợ single/multi mode, validation tự động và responsive layout.

Readme

@libs-ui/components-datetime-dropdown

Component dropdown chọn ngày tháng theo từng phần (năm, tháng, quý, ngày) với hỗ trợ single/multi mode, validation tự động và responsive layout.

Giới thiệu

LibsUiComponentsDatetimeDropdownComponent cung cấp giao diện chọn ngày tháng dạng dropdown riêng biệt cho từng đơn vị thời gian (năm, tháng, quý, ngày). Component hỗ trợ 6 định dạng hiển thị khác nhau qua typeFormat, chế độ chọn đơn (single) và chọn khoảng (multi từ/đến) với validation so sánh tự động giữa hai đầu. Layout tự động responsive — tự chuyển sang dạng dọc khi không đủ không gian ngang.

Tính năng

  • 6 định dạng: year, month, quarter, year-month, month-day, year-quarter
  • Chế độ single (chọn một thời điểm) và multi (chọn khoảng from-to)
  • Validation so sánh tự động: from phải nhỏ hơn to (có thể cấu hình)
  • Validation required với message tùy chỉnh
  • Responsive layout — tự động stack dọc khi không đủ không gian
  • Điều khiển từ bên ngoài qua FunctionsControl (checkIsValid, resetError, resetTime)
  • Hỗ trợ disable từng key (năm/tháng/quý/ngày) cho from và to riêng biệt
  • Ẩn các giá trị cụ thể trong dropdown (hiddenDate)
  • Tích hợp ILabel từ @libs-ui/components-label

Khi nào sử dụng

  • Khi cần chọn ngày tháng theo từng phần riêng biệt thay vì dùng calendar picker
  • Khi cần chọn khoảng thời gian from-to với validation so sánh tự động
  • Khi cần format hiển thị linh hoạt (year-month, month-day, year-quarter, ...)
  • Khi cần điều khiển validate và reset từ component cha (submit form, reset button)
  • Khi cần responsive layout tự động co giãn theo container

Cài đặt

npm install @libs-ui/components-datetime-dropdown

Import

import {
  LibsUiComponentsDatetimeDropdownComponent,
  IEmitSingleDateDropdown,
  IEmitMultiDateDropdown,
  IDateDropdownFunctionControlEvent,
  IFromAndToDateLabel,
  IValidDateDropdown,
  IDateDropdownDisableKeys,
  IDateDropdownDisable,
  IHiddenDate,
  TYPE_DATE_DROPDOWN_FORMAT,
  TYPE_DATE_FORMAT,
} from '@libs-ui/components-datetime-dropdown';

Ví dụ sử dụng

1. Single mode — chọn tháng và ngày (mặc định)

// my-form.component.ts
import { Component } from '@angular/core';
import {
  LibsUiComponentsDatetimeDropdownComponent,
  IEmitSingleDateDropdown,
  IDateDropdownFunctionControlEvent,
} from '@libs-ui/components-datetime-dropdown';

@Component({
  selector: 'app-my-form',
  standalone: true,
  imports: [LibsUiComponentsDatetimeDropdownComponent],
  templateUrl: './my-form.component.html',
})
export class MyFormComponent {
  private dropdownControl?: IDateDropdownFunctionControlEvent;

  handlerFunctionsControl(event: IDateDropdownFunctionControlEvent): void {
    event.stopPropagation();
    this.dropdownControl = event;
  }

  handlerSingleDateSelected(event: IEmitSingleDateDropdown): void {
    event.stopPropagation();
    console.log('Tháng:', event.month, 'Ngày:', event.day);
  }
}
<!-- my-form.component.html -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'month-day'"
  (outChooseSingleDate)="handlerSingleDateSelected($event)"
  (outFunctionsControl)="handlerFunctionsControl($event)"
/>

2. Các định dạng khác nhau

<!-- Chỉ năm — đảo ngược, giới hạn từ 2020 đến 2030 -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'year'"
  [reverseYear]="true"
  [minYear]="2020"
  [maxYear]="2030"
  (outChooseSingleDate)="handlerYearSelected($event)"
/>

<!-- Năm - tháng -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'year-month'"
  (outChooseSingleDate)="handlerYearMonthSelected($event)"
/>

<!-- Năm - quý -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'year-quarter'"
  (outChooseSingleDate)="handlerYearQuarterSelected($event)"
/>

<!-- Chỉ quý -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'quarter'"
  (outChooseSingleDate)="handlerQuarterSelected($event)"
/>
handlerYearSelected(event: IEmitSingleDateDropdown): void {
  event.stopPropagation();
  console.log('Năm:', event.year);
}

handlerYearMonthSelected(event: IEmitSingleDateDropdown): void {
  event.stopPropagation();
  console.log('Năm:', event.year, 'Tháng:', event.month);
}

handlerYearQuarterSelected(event: IEmitSingleDateDropdown): void {
  event.stopPropagation();
  console.log('Năm:', event.year, 'Quý:', event.quarter);
}

handlerQuarterSelected(event: IEmitSingleDateDropdown): void {
  event.stopPropagation();
  console.log('Quý:', event.quarter);
}

3. Multi mode — chọn khoảng thời gian from-to

// date-range-filter.component.ts
import { Component, signal } from '@angular/core';
import {
  LibsUiComponentsDatetimeDropdownComponent,
  IEmitMultiDateDropdown,
  IEmitSingleDateDropdown,
  IDateDropdownFunctionControlEvent,
} from '@libs-ui/components-datetime-dropdown';

@Component({
  selector: 'app-date-range-filter',
  standalone: true,
  imports: [LibsUiComponentsDatetimeDropdownComponent],
  templateUrl: './date-range-filter.component.html',
})
export class DateRangeFilterComponent {
  private dropdownControl?: IDateDropdownFunctionControlEvent;

  // Giá trị khởi tạo ban đầu (từ tháng 1 đến tháng 6 năm 2024)
  readonly selectedRange: IEmitMultiDateDropdown = {
    from: signal<IEmitSingleDateDropdown>({ year: 2024, month: 1 }),
    to: signal<IEmitSingleDateDropdown>({ year: 2024, month: 6 }),
  };

  handlerFunctionsControl(event: IDateDropdownFunctionControlEvent): void {
    event.stopPropagation();
    this.dropdownControl = event;
  }

  handlerMultiDateSelected(event: IEmitMultiDateDropdown): void {
    event.stopPropagation();
    console.log('Từ:', event.from());
    console.log('Đến:', event.to());
  }

  async handlerSubmit(): Promise<void> {
    const isValid = await this.dropdownControl?.checkIsValid();
    if (!isValid) {
      return;
    }
    // Tiến hành submit
  }

  async handlerReset(): Promise<void> {
    await this.dropdownControl?.resetTime?.();
    await this.dropdownControl?.resetError?.();
  }
}
<!-- date-range-filter.component.html -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'year-month'"
  [isMultiple]="true"
  [selectedDateTime]="selectedRange"
  [fromAndToDateLabel]="{ from: 'i18n_label_from', to: 'i18n_to' }"
  [validRequired]="{ message: 'i18n_required', messageValidCompareTime: 'i18n_invalid_end_date_selected' }"
  (outChooseMultiDate)="handlerMultiDateSelected($event)"
  (outFunctionsControl)="handlerFunctionsControl($event)"
/>

<button (click)="handlerSubmit()">Tìm kiếm</button>
<button (click)="handlerReset()">Xóa bộ lọc</button>

4. Disable từng key (năm/tháng/quý/ngày) riêng biệt

// filter.component.ts
import { Component, signal } from '@angular/core';
import {
  LibsUiComponentsDatetimeDropdownComponent,
  IEmitMultiDateDropdown,
  IDateDropdownDisableKeys,
} from '@libs-ui/components-datetime-dropdown';

@Component({
  selector: 'app-filter',
  standalone: true,
  imports: [LibsUiComponentsDatetimeDropdownComponent],
  templateUrl: './filter.component.html',
})
export class FilterComponent {
  // Disable quý 1 và quý 4 cho phía "from"
  readonly disabledKeys: IDateDropdownDisableKeys = {
    from: signal({
      quarter: signal([1, 4]),
    }),
    to: signal({
      quarter: signal([]),
    }),
  };

  handlerMultiDateSelected(event: IEmitMultiDateDropdown): void {
    event.stopPropagation();
    console.log('Khoảng:', event.from(), event.to());
  }
}
<!-- filter.component.html -->
<libs_ui-components-datetime-dropdown
  [typeFormat]="'year-quarter'"
  [isMultiple]="true"
  [listKeysDisable]="disabledKeys"
  (outChooseMultiDate)="handlerMultiDateSelected($event)"
/>

5. Với label và emit liên tục mỗi lần chọn

import { Component, signal } from '@angular/core';
import {
  LibsUiComponentsDatetimeDropdownComponent,
  IEmitSingleDateDropdown,
  IEmitMultiDateDropdown,
} from '@libs-ui/components-datetime-dropdown';
import { ILabel } from '@libs-ui/components-label';

@Component({
  selector: 'app-with-label',
  standalone: true,
  imports: [LibsUiComponentsDatetimeDropdownComponent],
  templateUrl: './with-label.component.html',
})
export class WithLabelComponent {
  readonly labelConfig: ILabel = {
    labelLeft: 'Kỳ báo cáo',
    required: true,
  };

  handlerSelectedDropdown(event: IEmitSingleDateDropdown | IEmitMultiDateDropdown): void {
    event.stopPropagation();
    console.log('Giá trị vừa chọn:', event);
  }
}
<libs_ui-components-datetime-dropdown
  [typeFormat]="'year-month'"
  [labelConfig]="labelConfig"
  [isEmitAfterChanged]="true"
  (outSelectedDropdown)="handlerSelectedDropdown($event)"
/>

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [classIncludeTextDisplayWhenNoSelect] | string \| undefined | undefined | CSS class tùy chỉnh cho text hiển thị khi chưa chọn giá trị | [classIncludeTextDisplayWhenNoSelect]="'text-gray-400'" | | [disable] | boolean | false | Vô hiệu hóa toàn bộ component | [disable]="true" | | [disableSecond] | boolean | false | Vô hiệu hóa dropdown thứ hai cho đến khi dropdown đầu tiên được chọn | [disableSecond]="true" | | [fromAndToDateLabel] | IFromAndToDateLabel | { from: 'i18n_label_from', to: 'i18n_to' } | Tùy chỉnh label From/To và CSS class của chúng khi isMultiple=true | [fromAndToDateLabel]="{ from: 'Từ', to: 'Đến' }" | | [getItemYearDisplay] | (year: string) => string | undefined | Hàm tùy chỉnh cách hiển thị label năm trong dropdown | [getItemYearDisplay]="formatYear" | | [hiddenDate] | IHiddenDate \| undefined | undefined | Ẩn các giá trị ngày/tháng cụ thể khỏi danh sách dropdown | [hiddenDate]="hiddenConfig" | | [ignoreAllowTimeEqual] | boolean | true | Khi true: from phải nhỏ hơn to (không cho bằng nhau). Khi false: from có thể bằng to | [ignoreAllowTimeEqual]="false" | | [ignoreConvertYearSelected] | boolean | false | Hiển thị giá trị năm gốc thay vì qua i18n convert | [ignoreConvertYearSelected]="true" | | [ignoreFromAndToDateLabel] | boolean | false | Ẩn label From/To, chỉ hiển thị dấu - ngăn cách | [ignoreFromAndToDateLabel]="true" | | [ignoreRequiredValueSecondWhenNotValidRequired] | boolean | false | Bỏ qua validate giá trị thứ hai khi validRequired không được cấu hình | [ignoreRequiredValueSecondWhenNotValidRequired]="true" | | [ignoreValidTimeCompare] | boolean | false | Bỏ qua validation so sánh từ/đến (hữu ích khi chỉ cần validate required) | [ignoreValidTimeCompare]="true" | | [isBorderError] | boolean | false | Hiển thị viền đỏ lỗi trên tất cả dropdown | [isBorderError]="hasError" | | [isCheckErrorWhenSelectItem] | boolean | true | Tự động kiểm tra và hiển thị lỗi mỗi khi người dùng chọn một item | [isCheckErrorWhenSelectItem]="false" | | [isEmitAfterChanged] | boolean | false | Emit outSelectedDropdown mỗi lần chọn giá trị (kể cả khi chưa chọn đủ). Cần check undefined cẩn thận | [isEmitAfterChanged]="true" | | [isMultiple] | boolean | false | Bật chế độ chọn khoảng thời gian — hiển thị hai nhóm dropdown (From/To) với validation so sánh | [isMultiple]="true" | | [labelConfig] | ILabel \| undefined | undefined | Cấu hình label phía trên component, dùng ILabel từ @libs-ui/components-label | [labelConfig]="{ labelLeft: 'Kỳ báo cáo', required: true }" | | [listHasButtonUnSelectOption] | boolean | false | Hiển thị nút "Bỏ chọn" trong danh sách dropdown | [listHasButtonUnSelectOption]="true" | | [listKeysDisable] | IDateDropdownDisableKeys \| undefined | undefined | Cấu hình disable từng giá trị (năm/tháng/quý/ngày) cho from và to riêng biệt | [listKeysDisable]="disabledKeys" | | [listMaxItemShow] | { year?: number; month?: number; quarter?: number; day?: number } \| undefined | undefined | Giới hạn số lượng item tối đa hiển thị trong dropdown cho từng loại | [listMaxItemShow]="{ year: 5 }" | | [maxYear] | number | 0 (dùng DEFAULT_MAX_YEAR từ picker) | Năm tối đa hiển thị trong dropdown năm | [maxYear]="2030" | | [minWidth] | number \| undefined | undefined | Chiều rộng tối thiểu của toàn bộ component (px) | [minWidth]="200" | | [minYear] | number | 0 (dùng DEFAULT_MIN_YEAR từ picker) | Năm tối thiểu hiển thị trong dropdown năm | [minYear]="2020" | | [readonly] | boolean | false | Chế độ chỉ đọc — hiển thị giá trị nhưng không cho phép thay đổi | [readonly]="true" | | [reverseYear] | boolean \| undefined | undefined | Đảo ngược thứ tự danh sách năm (năm mới nhất hiển thị trên đầu) | [reverseYear]="true" | | [selectedDateTime] | IEmitMultiDateDropdown \| undefined | undefined | Giá trị khởi tạo — phải dùng WritableSignal bên trong (xem interface IEmitMultiDateDropdown) | [selectedDateTime]="selectedRange" | | [typeFormat] | TYPE_DATE_DROPDOWN_FORMAT | 'month-day' | Định dạng dropdown hiển thị: 'year', 'month', 'quarter', 'year-month', 'month-day', 'year-quarter' | [typeFormat]="'year-month'" | | [validRequired] | IValidDateDropdown \| undefined | undefined | Cấu hình validation bắt buộc với message lỗi tùy chỉnh | [validRequired]="{ message: 'i18n_required' }" | | [widthByElement] | boolean | false | Tự động tính chiều rộng dropdown theo kích thước phần tử cha | [widthByElement]="true" | | [widthDropdown] | number | 136 | Chiều rộng (px) của mỗi ô dropdown đơn lẻ | [widthDropdown]="160" | | [zIndex] | number | 1200 | z-index của dropdown overlay khi mở | [zIndex]="1300" |

@Output()

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outChangStageFlagMouse) | IFlagMouse | Emit khi trạng thái chuột thay đổi (hover/leave trên dropdown) | handlerFlagMouseChange(event: IFlagMouse): void { event.stopPropagation(); ... } | (outChangStageFlagMouse)="handlerFlagMouseChange($event)" | | (outChooseMultiDate) | IEmitMultiDateDropdown | Emit khi người dùng chọn đầy đủ cả From và To (chỉ khi isMultiple=true). Chỉ emit khi cả hai hợp lệ | handlerMultiDateSelected(event: IEmitMultiDateDropdown): void { event.stopPropagation(); ... } | (outChooseMultiDate)="handlerMultiDateSelected($event)" | | (outChooseSingleDate) | IEmitSingleDateDropdown | Emit khi người dùng chọn đầy đủ tất cả các trường theo typeFormat (chỉ khi isMultiple=false) | handlerSingleDateSelected(event: IEmitSingleDateDropdown): void { event.stopPropagation(); ... } | (outChooseSingleDate)="handlerSingleDateSelected($event)" | | (outFunctionsControl) | IDateDropdownFunctionControlEvent | Emit object chứa các hàm điều khiển component từ bên ngoài. Được emit một lần trong ngOnInit | handlerFunctionsControl(event: IDateDropdownFunctionControlEvent): void { event.stopPropagation(); this.ctrl = event; } | (outFunctionsControl)="handlerFunctionsControl($event)" | | (outSelectedDropdown) | IEmitSingleDateDropdown \| IEmitMultiDateDropdown | Emit mỗi khi người dùng chọn bất kỳ giá trị nào. Chỉ hoạt động khi isEmitAfterChanged=true. Lưu ý: cần kiểm tra undefined kỹ khi sử dụng | handlerSelectedDropdown(event: IEmitSingleDateDropdown \| IEmitMultiDateDropdown): void { event.stopPropagation(); ... } | (outSelectedDropdown)="handlerSelectedDropdown($event)" |

FunctionsControl (IDateDropdownFunctionControlEvent)

Nhận qua (outFunctionsControl), dùng để điều khiển component từ bên ngoài (thường là từ nút Submit/Reset của form).

| Method | Signature | Mô tả | |---|---|---| | checkIsValid() | () => Promise<boolean> | Kiểm tra toàn bộ validation (required + so sánh from/to). Trả về false nếu có lỗi và hiển thị trạng thái lỗi trên UI | | resetError() | () => Promise<void> | Xóa tất cả trạng thái lỗi đang hiển thị trên component | | resetTime() | () => Promise<void> | Reset toàn bộ giá trị đã chọn về trạng thái trống |

// Sử dụng FunctionsControl trong form submit
private dropdownControl?: IDateDropdownFunctionControlEvent;

handlerFunctionsControl(event: IDateDropdownFunctionControlEvent): void {
  event.stopPropagation();
  this.dropdownControl = event;
}

async handlerSubmit(): Promise<void> {
  const isValid = await this.dropdownControl?.checkIsValid();
  if (!isValid) {
    return; // dừng lại nếu có lỗi
  }
  // tiến hành submit
}

async handlerReset(): Promise<void> {
  await this.dropdownControl?.resetTime?.();
  await this.dropdownControl?.resetError?.();
}

Types & Interfaces

import {
  TYPE_DATE_DROPDOWN_FORMAT,
  TYPE_DATE_FORMAT,
  IEmitSingleDateDropdown,
  IEmitMultiDateDropdown,
  IFromAndToDateLabel,
  IDateDropdownFunctionControlEvent,
  IValidDateDropdown,
  IHiddenDate,
  IDateDropdownDisableKeys,
  IDateDropdownDisable,
} from '@libs-ui/components-datetime-dropdown';

TYPE_DATE_DROPDOWN_FORMAT

Format truyền vào [typeFormat] — quyết định dropdown nào xuất hiện:

type TYPE_DATE_DROPDOWN_FORMAT =
  | 'year'          // 1 dropdown: năm
  | 'month'         // 1 dropdown: tháng
  | 'quarter'       // 1 dropdown: quý
  | 'year-month'    // 2 dropdown: năm + tháng
  | 'month-day'     // 2 dropdown: tháng + ngày (mặc định)
  | 'year-quarter'  // 2 dropdown: năm + quý
  | string;         // custom format (ít dùng)

TYPE_DATE_FORMAT

type TYPE_DATE_FORMAT = 'year' | 'month' | 'quarter' | 'day';

IEmitSingleDateDropdown

Dữ liệu emit khi chọn single date (qua outChooseSingleDate). Chỉ có các trường tương ứng với typeFormat:

interface IEmitSingleDateDropdown {
  year?: number;
  month?: number;
  quarter?: number;
  day?: number;
}

// Ví dụ: typeFormat="year-month" → { year: 2024, month: 6 }
// Ví dụ: typeFormat="month-day"  → { month: 3, day: 15 }
// Ví dụ: typeFormat="year"       → { year: 2024 }

IEmitMultiDateDropdown

Dữ liệu khởi tạo (selectedDateTime) và emit khi chọn multi date (outChooseMultiDate). Dùng WritableSignal:

interface IEmitMultiDateDropdown {
  from: WritableSignal<IEmitSingleDateDropdown>;
  to: WritableSignal<IEmitSingleDateDropdown>;
}

// Tạo giá trị khởi tạo:
import { signal } from '@angular/core';
const selectedRange: IEmitMultiDateDropdown = {
  from: signal<IEmitSingleDateDropdown>({ year: 2024, month: 1 }),
  to: signal<IEmitSingleDateDropdown>({ year: 2024, month: 12 }),
};

// Đọc giá trị:
console.log(event.from()); // { year: 2024, month: 1 }
console.log(event.to());   // { year: 2024, month: 12 }

IDateDropdownFunctionControlEvent

interface IDateDropdownFunctionControlEvent {
  checkIsValid: () => Promise<boolean>;
  resetError?: () => Promise<void>;
  resetTime?: () => Promise<void>;
}

IValidDateDropdown

Cấu hình message lỗi cho validation. Dùng với i18n key:

interface IValidDateDropdown {
  message?: string;                           // i18n key cho lỗi required
  interpolateParams?: { any: object };         // params cho message
  messageValidCompareTime?: string;            // i18n key cho lỗi so sánh from > to
  interpolateParamsCompareTime?: { any: object }; // params cho messageValidCompareTime
}

// Ví dụ:
const validRequired: IValidDateDropdown = {
  message: 'i18n_required',
  messageValidCompareTime: 'i18n_invalid_end_date_selected',
};

IFromAndToDateLabel

interface IFromAndToDateLabel {
  from?: string;          // i18n key hoặc text trực tiếp cho label "From"
  to?: string;            // i18n key hoặc text trực tiếp cho label "To"
  classLabelFrom?: string; // CSS class tùy chỉnh cho label "From"
  classLabelTo?: string;   // CSS class tùy chỉnh cho label "To"
}

IDateDropdownDisableKeys

Cấu hình disable từng giá trị cho from và to riêng biệt:

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>>;
}

// Ví dụ: disable tháng 1 và tháng 2 cho "from"
import { signal } from '@angular/core';
const disabledKeys: IDateDropdownDisableKeys = {
  from: signal({
    month: signal([1, 2]),
  }),
};

IHiddenDate

Ẩn hoàn toàn các giá trị cụ thể khỏi danh sách dropdown:

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>;
  }>>>;
}

Lưu ý quan trọng

⚠️ selectedDateTime dùng WritableSignal: Input [selectedDateTime] nhận IEmitMultiDateDropdown trong đó fromtoWritableSignal. Phải khởi tạo đúng: { from: signal({ year: 2024 }), to: signal({ year: 2024 }) }.

⚠️ typeFormat quyết định số dropdown: 'year-month' tạo 2 dropdown (năm + tháng), 'year' tạo 1 dropdown. Output event chỉ có các trường tương ứng với format đã chọn.

⚠️ outChooseMultiDate chỉ emit khi đầy đủ: Ở multi mode, outChooseMultiDate chỉ emit khi cả from và to đều được chọn đầy đủ. Nếu cần emit từng lần chọn, dùng [isEmitAfterChanged]="true" kết hợp (outSelectedDropdown).

⚠️ outSelectedDropdown cần check undefined: Khi dùng [isEmitAfterChanged]="true", output (outSelectedDropdown) có thể emit giá trị chưa đầy đủ. Luôn kiểm tra các trường trước khi sử dụng.

⚠️ ignoreAllowTimeEqual mặc định true: Mặc định from phải nhỏ hơn to (không cho bằng nhau). Đặt [ignoreAllowTimeEqual]="false" nếu muốn cho phép from = to.

⚠️ widthDropdown áp dụng cho từng dropdown đơn: Khi typeFormat="year-month"widthDropdown=136, tổng chiều rộng sẽ là khoảng 136 * 2 + spacing. Dùng [widthByElement]="true" để component tự tính theo container cha.

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/datetime/dropdown