@libs-ui/components-buttons-select-color
Component Button Select Color với color picker tích hợp, hỗ trợ chế độ apply ngay hoặc apply sau.
Giới thiệu
LibsUiComponentsButtonsSelectColorComponent là một standalone Angular component được thiết kế để hiển thị button với color picker popover. Component hỗ trợ 2 chế độ: apply ngay (applyNow) khi chọn màu hoặc chọn trước rồi bấm nút Apply.
Tính năng
- ✅ 2 chế độ: Apply ngay hoặc Apply sau
- ✅ Color picker với đầy đủ định dạng (HEX, RGB, RGBA, HSL, HSLA)
- ✅ Tùy chỉnh button trigger
- ✅ Hỗ trợ external content (custom trigger)
- ✅ Tích hợp popover với nhiều tùy chọn vị trí
- ✅ Emit multiple color formats cùng lúc
- ✅ Tùy chỉnh color picker options
- ✅ Angular Signals cho tính phản hồi cao
- ✅ OnPush Change Detection tối ưu hiệu năng
- ✅ Auto cleanup khi destroy component
Khi nào sử dụng
- Khi cần cho phép user chọn màu sắc
- Khi cần color picker với nhiều định dạng màu
- Khi cần preview màu trước khi apply (applyNow = false)
- Phù hợp cho theme customization, design tools, color settings
Cài đặt
npm install @libs-ui/components-buttons-select-color
yarn add @libs-ui/components-buttons-select-color
Import
import { LibsUiComponentsButtonsSelectColorComponent } from '@libs-ui/components-buttons-select-color';
import { IPickerCustomOptions, IOutputColorChangeMultipleType } from '@libs-ui/components-color-picker';
import { IButton } from '@libs-ui/components-buttons-button';
@Component({
standalone: true,
imports: [LibsUiComponentsButtonsSelectColorComponent],
})
export class YourComponent {}
Ví dụ
Basic - Apply Ngay
<libs_ui-components-buttons-select_color
[button]="{ label: 'Select Color' }"
[applyNow]="true"
(outColorChange)="handleColorChange($event)" />
handleColorChange(color: string) {
console.log('Selected color:', color);
}
With Apply Button
<libs_ui-components-buttons-select_color
[button]="{ label: 'Choose Color' }"
[applyNow]="false"
(outColorChange)="handleColorChange($event)"
(outColorChangeMultipleType)="handleMultipleTypes($event)" />
handleColorChange(color: string) {
console.log('Applied color:', color);
}
handleMultipleTypes(colors: IOutputColorChangeMultipleType) {
console.log('HEX:', colors.hex);
console.log('RGB:', colors.rgb);
console.log('RGBA:', colors.rgba);
console.log('HSL:', colors.hsl);
console.log('HSLA:', colors.hsla);
console.log('Alpha:', colors.alpha);
}
Custom Button Style
<libs_ui-components-buttons-select_color
[button]="{
label: 'Pick Color',
type: 'button-secondary',
classIconLeft: 'libs-ui-icon-color-palette'
}"
[applyNow]="true"
(outColorChange)="handleColorChange($event)" />
Custom Color Picker Options
<libs_ui-components-buttons-select_color
[button]="{ label: 'Select Color' }"
[customOptions]="{
color: '#ff5733',
showAlpha: true,
showHex: true,
showRgb: true,
showHsl: false,
format: 'hex'
}"
[applyNow]="true"
(outColorChange)="handleColorChange($event)" />
customOptions: IPickerCustomOptions = {
color: '#ff5733',
showAlpha: true,
showHex: true,
showRgb: true,
showHsl: false,
format: 'hex',
};
External Content (Custom Trigger)
<libs_ui-components-buttons-select_color
[externalContent]="true"
[applyNow]="true"
(outColorChange)="handleColorChange($event)">
<div class="libs-ui-buttons-select-color">
<div
class="w-10 h-10 rounded border-2 border-gray-300 cursor-pointer"
[style.background-color]="selectedColor"></div>
</div>
</libs_ui-components-buttons-select_color>
selectedColor = '#3b82f6';
handleColorChange(color: string) {
this.selectedColor = color;
}
Different Popover Directions
<libs_ui-components-buttons-select_color
[button]="{ label: 'Bottom' }"
[direction]="'bottom'"
[applyNow]="true" />
<libs_ui-components-buttons-select_color
[button]="{ label: 'Top' }"
[direction]="'top'"
[applyNow]="true" />
<libs_ui-components-buttons-select_color
[button]="{ label: 'Left' }"
[direction]="'left'"
[applyNow]="true" />
<libs_ui-components-buttons-select_color
[button]="{ label: 'Right' }"
[direction]="'right'"
[applyNow]="true" />
Icon Only Button
<libs_ui-components-buttons-select_color
[button]="{
classIconLeft: 'libs-ui-icon-color-palette',
iconOnlyType: true
}"
[applyNow]="true"
(outColorChange)="handleColorChange($event)" />
With Custom Z-Index
<libs_ui-components-buttons-select_color
[button]="{ label: 'Select Color' }"
[(zIndex)]="customZIndex"
[applyNow]="true"
(outColorChange)="handleColorChange($event)" />
customZIndex = 2000;
API
libs_ui-components-buttons-select_color
Inputs
[applyNow] | boolean | false | Nếu true: chọn xong tự emit; false: cần bấm Apply |
[button] | IButton | undefined | Cấu hình button trigger |
[customOptions] | IPickerCustomOptions | undefined | Tùy chỉnh color picker options |
[direction] | TYPE_POPOVER_DIRECTION | 'bottom' | Hướng hiển thị popover |
[externalContent] | boolean | false | Sử dụng custom content thay vì button mặc định |
[(zIndex)] | number | 1200 | Z-index của popover (two-way binding) |
Outputs
(outColorChange) | string | Emit màu đã chọn (format theo customOptions) |
(outColorChangeMultipleType) | IOutputColorChangeMultipleType | Emit tất cả các định dạng màu cùng lúc |
Content Projection
div.libs-ui-buttons-select-color | Custom trigger content (khi externalContent=true) |
Types & Interfaces
IButton Interface
export interface IButton {
key?: string;
type?: TYPE_BUTTON;
sizeButton?: TYPE_SIZE_BUTTON;
iconOnlyType?: boolean;
label?: string;
disable?: boolean;
classInclude?: string;
classIconLeft?: string;
classIconRight?: string;
classLabel?: string;
popover?: IPopover;
ignoreStopPropagationEvent?: boolean;
zIndex?: number;
isPending?: boolean;
action?: (data?: any) => Promise<void>;
styleIconLeft?: Record<string, any>;
styleButton?: Record<string, any>;
buttonCustom?: IColorButton;
}
IPickerCustomOptions Interface
export interface IPickerCustomOptions {
slBarSize?: Array<number>;
hueBarSize?: Array<number>;
alphaBarSize?: Array<number>;
showHsl?: boolean;
showRgb?: boolean;
showHex?: boolean;
showAlpha?: boolean;
color?: string | Array<number>;
format?: 'rgb' | 'rgba' | 'hsl' | 'hsla' | 'hex' | 'color';
}
IOutputColorChangeMultipleType Interface
export interface IOutputColorChangeMultipleType {
rgba: string;
rgb: string;
hex: string;
hsl: string;
hsla: string;
alpha: number;
}
TYPE_POPOVER_DIRECTION
export type TYPE_POPOVER_DIRECTION = 'top' | 'bottom' | 'left' | 'right';
Behavior
Apply Now Mode (applyNow = true)
- Khi chọn màu, component tự động emit
outColorChange và outColorChangeMultipleType
- Không hiển thị Cancel/Apply buttons
- Popover vẫn mở sau khi chọn màu (user có thể tiếp tục điều chỉnh)
Apply Later Mode (applyNow = false)
- Khi chọn màu, component lưu tạm thời màu đã chọn
- Hiển thị Cancel và Apply buttons
- Click Cancel: đóng popover, không emit event
- Click Apply: emit
outColorChange và outColorChangeMultipleType, sau đó đóng popover
Popover Management
- Component tự động cleanup popover khi destroy (ngOnDestroy)
- Popover có thể được đóng bằng cách click outside (click-toggle mode)
- Z-index có thể được điều chỉnh để tránh conflicts
Công nghệ
| Angular | 18+ | Framework |
| Angular Signals | - | State management |
| TailwindCSS | 3.x | Styling |
| OnPush | - | Change Detection |
Demo
npx nx serve core-ui
Truy cập: http://localhost:4500/buttons/select-color
Unit Tests
npx nx test buttons-select-color
npx nx test buttons-select-color --coverage
npx nx test buttons-select-color --watch
Dependencies
@angular/core: >=18.0.0
@libs-ui/components-buttons-button: 0.2.355-14
@libs-ui/components-color-picker: 0.2.355-14
@libs-ui/components-popover: 0.2.355-14
@ngx-translate/core: ^15.0.0
Important Notes
⚠️ External Content Selector
Khi sử dụng [externalContent]="true", content projection PHẢI có class libs-ui-buttons-select-color:
<libs_ui-components-buttons-select_color [externalContent]="true">
<div class="libs-ui-buttons-select-color">
</div>
</libs_ui-components-buttons-select_color>
⚠️ Color Format
outColorChange emit màu theo format được chỉ định trong customOptions.format
- Nếu không chỉ định format, mặc định là format của màu input
outColorChangeMultipleType luôn emit tất cả các formats
⚠️ Z-Index Management
- Default z-index là 1200
- Nếu có conflicts với modals/dialogs khác, tăng z-index
- Z-index hỗ trợ two-way binding:
[(zIndex)]="myZIndex"
⚠️ Memory Management
Component tự động cleanup popover trong ngOnDestroy. Không cần manual cleanup.
Best Practices
- Sử dụng applyNow cho simple use cases: Nếu không cần preview, dùng
applyNow="true" để UX tốt hơn
- Handle multiple formats: Sử dụng
outColorChangeMultipleType khi cần lưu nhiều formats
- Custom trigger cho special cases: Dùng
externalContent khi cần custom UI (color swatch, preview box...)
- Set initial color: Luôn set
customOptions.color để có màu khởi tạo
- Responsive z-index: Điều chỉnh z-index phù hợp với layout hierarchy
Troubleshooting
Color picker không hiển thị
- Kiểm tra z-index có bị overlap bởi elements khác không
- Verify
@libs-ui/components-color-picker đã được install
- Check console errors
External content không hoạt động
- Đảm bảo có class
libs-ui-buttons-select-color trên wrapper div
- Verify
[externalContent]="true" được set
- Check content projection syntax
Màu không đúng format
- Kiểm tra
customOptions.format setting
- Verify input color format hợp lệ
- Use
outColorChangeMultipleType để có tất cả formats
Popover không đóng
- Component tự động cleanup trong ngOnDestroy
- Nếu cần đóng manual, có thể trigger click outside
- Check không có errors trong console
License
MIT