> Component Dropdown Button với menu tùy chọn, hỗ trợ chế độ apply ngay hoặc apply sau.
npm install @libs-ui/components-buttons-dropdown> Component Dropdown Button với menu tùy chọn, hỗ trợ chế độ apply ngay hoặc apply sau.
LibsUiComponentsButtonsDropdownComponent là một standalone Angular component được thiết kế để hiển thị button với dropdown menu. Component hỗ trợ 2 chế độ: apply ngay (applyNow) khi chọn item hoặc chọn trước rồi bấm nút Apply.
- ✅ 2 chế độ: Apply ngay hoặc Apply sau
- ✅ Tùy chỉnh field hiển thị và key field
- ✅ Two-way binding cho item được chọn
- ✅ Tích hợp popover với nhiều tùy chọn vị trí
- ✅ Hỗ trợ icon cho từng item
- ✅ Hỗ trợ custom template cho item
- ✅ Disable state cho button và từng item
- ✅ Angular Signals cho tính phản hồi cao
- ✅ OnPush Change Detection tối ưu hiệu năng
- Khi cần hiển thị danh sách tùy chọn trong dropdown menu
- Khi cần cho phép user chọn một item từ danh sách
- Khi cần chế độ preview trước khi apply (applyNow = false)
- Phù hợp cho filter buttons, action menus, selection dropdowns
``bashnpm
npm install @libs-ui/components-buttons-dropdown
Import
`typescript
import { LibsUiComponentsButtonsDropdownComponent, IButtonDropdown, IPopupConfigButtonDropdown } from '@libs-ui/components-buttons-dropdown';@Component({
standalone: true,
imports: [LibsUiComponentsButtonsDropdownComponent],
// ...
})
export class YourComponent {}
`Ví dụ
$3
`html
label="Select Option"
[items]="options"
[applyNow]="true"
(outSelectItem)="handleSelect($event)" />
``typescript
options = [
{ key: '1', label: 'Option 1' },
{ key: '2', label: 'Option 2' },
{ key: '3', label: 'Option 3' }
];handleSelect(item: any) {
console.log('Selected:', item);
}
`$3
`html
label="Select Option"
[items]="options"
[applyNow]="false"
[(keySelected)]="selectedKey"
(outApply)="handleApply($event)" />
``typescript
selectedKey = '1';handleApply(item: any) {
console.log('Applied:', item);
}
`$3
`html
label="Select User"
[items]="users"
fieldDisplay="name"
keyField="id"
[applyNow]="true"
(outSelectItem)="handleSelect($event)" />
``typescript
users = [
{ id: 'u1', name: 'John Doe' },
{ id: 'u2', name: 'Jane Smith' },
{ id: 'u3', name: 'Bob Johnson' },
];
`$3
`html
label="Actions"
[items]="actions"
fieldClassIconLeft="iconClass"
[applyNow]="true"
(outSelectItem)="handleAction($event)" />
``typescript
actions = [
{ key: 'edit', label: 'Edit', iconClass: 'libs-ui-icon-edit' },
{ key: 'delete', label: 'Delete', iconClass: 'libs-ui-icon-delete' },
{ key: 'share', label: 'Share', iconClass: 'libs-ui-icon-share' },
];
`$3
`html
label="Options"
[items]="options"
[popupConfig]="{
width: 300,
maxHeight: 200,
direction: 'bottom',
zIndex: 1500
}"
[applyNow]="true" />
`$3
`html
label="Primary"
[items]="options"
typeButton="button-primary"
[applyNow]="true" />
label="Secondary"
[items]="options"
typeButton="button-secondary"
[applyNow]="true" />
label="Outline"
[items]="options"
typeButton="button-outline"
[applyNow]="true" />
`API
$3
#### Inputs
| Property | Type | Default | Description |
| -------------------------------------------- | ---------------------------- | ------------------------------------------ | ------------------------------------------------- |
|
[applyNow] | boolean | false | Nếu true: chọn xong tự emit; false: cần bấm Apply |
| [classIconLeft] | string | '' | Class icon bên trái button |
| [classIconRight] | string | 'libs-ui-icon-move-right rotate-[90deg]' | Class icon bên phải button |
| [classInclude] | string | '' | Class CSS bổ sung cho button |
| [classIncludeContainer] | string | undefined | Class CSS cho container |
| [classLabel] | string | '' | Class CSS cho label |
| [disable] | boolean | false | Disable button |
| [fieldClass] | string | 'class' | Tên field chứa class của item |
| [fieldClassIconLeft] | string | 'classIconLeft' | Tên field chứa icon class của item |
| [fieldDisplay] | string | 'label' | Tên field hiển thị của item |
| [iconOnlyType] | boolean | false | Chỉ hiển thị icon, ẩn label |
| [ignoreHiddenPopoverContentWhenMouseLeave] | boolean | true | Giữ popover mở khi chuột rời |
| [items] | Array | required | Danh sách items hiển thị |
| [keyField] | string | 'key' | Tên field làm key của item |
| [(keySelected)] | string | undefined | Key của item được chọn (two-way binding) |
| [label] | string | undefined | Label của button |
| [modePopover] | TYPE_POPOVER_MODE | 'click-toggle' | Chế độ hiển thị popover |
| [popupConfig] | IPopupConfigButtonDropdown | {...} | Cấu hình popup (width, height, direction...) |
| [showBorderBottom] | boolean | false | Hiển thị border dưới items |
| [sizeButton] | TYPE_SIZE_BUTTON | 'medium' | Kích thước button |
| [typeButton] | TYPE_BUTTON | 'button-primary' | Kiểu button |#### Outputs
| Property | Type | Description |
| ----------------------- | ------------------------------ | ------------------------------------------ |
|
(outApply) | any | Emit khi bấm Apply (chế độ applyNow=false) |
| (outFunctionsControl) | IPopoverFunctionControlEvent | Emit functions điều khiển popover |
| (outHover) | boolean | Emit khi hover state thay đổi |
| (outIconEvent) | MouseEvent | Emit khi click icon |
| (outPopoverEvent) | TYPE_POPOVER_EVENT | Emit events từ popover |
| (outSelectItem) | any | Emit khi chọn item |#### Public Methods
| Method | Description |
| ------------------ | --------------------------------------- |
|
FunctionsControl | Getter để lấy popover control functions |Types & Interfaces
`typescript
/**
* Interface cho Dropdown Button component
*/
export interface IButtonDropdown extends IButton {
/* Danh sách các mục sẽ hiển thị trong menu /
items: any[];
/* Tên trường dùng để hiển thị nội dung của mỗi mục /
fieldDisplay?: string;
/* Tên trường dùng làm giá trị key của mỗi mục /
keyField?: string;
/* Giá trị key đang được chọn (hỗ trợ two-way binding) /
keySelected?: string;
/* Nếu true: chọn xong tự emit sự kiện; false: cần bấm nút Áp dụng /
applyNow?: boolean;
/* Hiển thị đường kẻ dưới menu khi mở /
showBorderBottom?: boolean;
/* Cấu hình chi tiết cho popover (vị trí, kích thước) /
popupConfig?: IPopupConfigButtonDropdown;
/* Giữ popover mở khi chuột rời khỏi nội dung /
ignoreHiddenPopoverContentWhenMouseLeave?: boolean;
/* Cách hiển thị popover (click, hover,...) /
modePopover?: TYPE_POPOVER_MODE;
}/**
* Cấu hình cho Dropdown popover
*/
export interface IPopupConfigButtonDropdown {
width?: number;
maxWidth?: number;
maxHeight?: number;
zIndex?: number;
direction?: TYPE_POPOVER_DIRECTION;
timeDestroy?: number;
widthByParent?: boolean;
position?: {
mode: 'start' | 'center' | 'end';
distance: number;
};
classInclude?: string;
}
`Item Structure
Mỗi item trong array
items có thể có các thuộc tính:`typescript
interface DropdownItem {
// Required fields (tùy theo fieldDisplay và keyField)
[fieldDisplay]: string; // Mặc định: 'label'
[keyField]: string; // Mặc định: 'key' // Optional fields
class?: string; // Class cho item
classIconLeft?: string; // Icon class
classInclude?: string; // Class bổ sung
classRow?: string; // Class cho row
disable?: boolean; // Disable item
ignoreFlex?: boolean; // Không dùng flex layout
showPopover?: boolean; // Hiển thị popover cho item
popoverContent?: string; // Nội dung popover
subTemplate?: TemplateRef; // Custom template
buttonTemplateConfig?: {
// Config cho button trong item
icon?: string;
iconLeft?: string;
label?: string;
type?: TYPE_BUTTON;
action: (item: any, items: any[]) => void;
};
}
`Công nghệ
| Technology | Version | Purpose |
| --------------- | ------- | ---------------- |
| Angular | 18+ | Framework |
| Angular Signals | - | State management |
| TailwindCSS | 3.x | Styling |
| OnPush | - | Change Detection |
Demo
`bash
npx nx serve core-ui
`Truy cập:
http://localhost:4500/buttons/dropdownUnit Tests
`bash
Chạy tests
npx nx test components-buttons-dropdownCoverage
npx nx test components-buttons-dropdown --coverageWatch mode
npx nx test components-buttons-dropdown --watch
``MIT