@libs-ui/components-inputs-search
v0.2.357-9
Published
> Ô nhập liệu tìm kiếm với debounce tự động, hỗ trợ phím Enter, nút xóa nhanh và tùy chỉnh icon linh hoạt.
Downloads
4,178
Readme
@libs-ui/components-inputs-search
Ô nhập liệu tìm kiếm với debounce tự động, hỗ trợ phím Enter, nút xóa nhanh và tùy chỉnh icon linh hoạt.
Giới thiệu
@libs-ui/components-inputs-search là component ô tìm kiếm được xây dựng trên nền @libs-ui/components-inputs-input, bổ sung cơ chế debounce tự động để giảm số lần gọi API khi người dùng đang gõ. Component hỗ trợ phím Enter để kích hoạt tìm kiếm ngay lập tức (với throttle chống spam), nút xóa nội dung nhanh khi bật hasClearSearch, và đầy đủ các tuỳ chỉnh về icon, border, background thông qua searchConfig.
Tính năng
- Tự động emit
outSearchsau khoảng thời gian debounce (mặc định 1000ms) khi người dùng ngừng gõ - Emit
outSearchngay lập tức khi nhấn Enter (throttle cùng debounce time để chống spam) - Nút xóa nội dung nhanh (
hasClearSearch: true) xuất hiện khi ô có nội dung - Emit
outValueChangemỗi lần gõ phím để lắng nghe thay đổi tức thời - Tùy chỉnh icon trái/phải, placeholder, border, background, chiều cao qua
searchConfig - Hỗ trợ
disable,readonly,ignoreAutoComplete - Cung cấp
outFunctionsControlđể điều khiển programmatically (focus, blur, reset) - Hoạt động với Angular Signals và
ChangeDetectionStrategy.OnPush
Khi nào sử dụng
- Khi cần ô tìm kiếm tự động gửi yêu cầu sau khi người dùng ngừng gõ (debounce) thay vì gửi mỗi keystroke
- Khi cần tích hợp tìm kiếm vào thanh lọc dữ liệu, bảng danh sách hoặc dropdown autocomplete
- Khi cần ô tìm kiếm có nút xóa nhanh để người dùng reset filter dễ dàng
- Khi cần lắng nghe cả hai luồng: giá trị tức thời (
outValueChange) và giá trị đã được debounce (outSearch)
Cài đặt
npm install @libs-ui/components-inputs-searchImport
import { LibsUiComponentsInputsSearchComponent } from '@libs-ui/components-inputs-search';
@Component({
standalone: true,
imports: [LibsUiComponentsInputsSearchComponent],
// ...
})
export class MyComponent {}Nếu cần dùng interface IInputSearchConfig:
import {
LibsUiComponentsInputsSearchComponent,
IInputSearchConfig,
} from '@libs-ui/components-inputs-search';Ví dụ sử dụng
Ví dụ 1 — Cơ bản
<libs_ui-components-inputs-search
[searchConfig]="{ placeholder: 'Tìm kiếm khách hàng...' }"
(outSearch)="handlerSearch($event)">
</libs_ui-components-inputs-search>handlerSearch(keyword: string): void {
// keyword đã được trim, chỉ emit sau debounce hoặc khi nhấn Enter
this.loadData({ search: keyword });
}Ví dụ 2 — Với placeholder và nút xóa nhanh
<libs_ui-components-inputs-search
[searchConfig]="{
placeholder: 'Tìm kiếm khách hàng...',
hasClearSearch: true
}"
(outSearch)="handlerSearch($event)">
</libs_ui-components-inputs-search>handlerSearch(keyword: string): void {
// keyword = '' khi người dùng nhấn nút xóa (X)
this.params.update(p => ({ ...p, search: keyword, page: 1 }));
this.loadList();
}Ví dụ 3 — Tùy chỉnh debounce và icon
<libs_ui-components-inputs-search
[debounceTime]="500"
[searchConfig]="{
iconLeftClass: 'libs-ui-icon-filter',
placeholder: 'Lọc nhanh...',
noBorder: true,
backgroundNone: true
}"
(outSearch)="handlerFilter($event)">
</libs_ui-components-inputs-search>handlerFilter(keyword: string): void {
this.filterKeyword.set(keyword);
}Ví dụ 4 — Lắng nghe từng keystroke (outValueChange)
<libs_ui-components-inputs-search
[ignoreAutoComplete]="true"
(outValueChange)="handlerValueChange($event)"
(outSearch)="handlerSearch($event)">
</libs_ui-components-inputs-search>handlerValueChange(keyword: string): void {
// Emit mỗi lần gõ — dùng để hiển thị gợi ý realtime
this.suggestionKeyword.set(keyword);
}
handlerSearch(keyword: string): void {
// Chỉ emit khi nhấn Enter (ignoreAutoComplete = true bỏ qua debounce)
this.executeSearch(keyword);
}Ví dụ 5 — Điều khiển programmatically qua FunctionsControl
<libs_ui-components-inputs-search
[searchConfig]="{ placeholder: 'Tìm kiếm...' }"
(outFunctionsControl)="handlerFunctionsControl($event)"
(outSearch)="handlerSearch($event)">
</libs_ui-components-inputs-search>import { IInputFunctionControlEvent } from '@libs-ui/components-inputs-input';
private searchControl: IInputFunctionControlEvent | undefined;
handlerFunctionsControl(control: IInputFunctionControlEvent): void {
this.searchControl = control;
}
// Focus ô tìm kiếm từ code
focusSearchInput(): void {
this.searchControl?.focus();
}
// Reset giá trị từ code
resetSearch(): void {
this.searchControl?.resetValue();
}
handlerSearch(keyword: string): void {
this.executeSearch(keyword);
}@Input()
| Input | Type | Default | Mô tả | Ví dụ |
|---|---|---|---|---|
| blurTimeOut | number | 600 | Thời gian chờ (ms) trước khi emit sự kiện blur | [blurTimeOut]="300" |
| debounceTime | number | 1000 | Thời gian chờ (ms) sau khi người dùng ngừng gõ để emit outSearch | [debounceTime]="500" |
| disable | boolean | false | Vô hiệu hóa toàn bộ ô tìm kiếm | [disable]="isLoading()" |
| focusTimeOut | number | 600 | Thời gian chờ (ms) trước khi emit sự kiện focus | [focusTimeOut]="300" |
| ignoreAutoComplete | boolean | undefined | Nếu true, bỏ qua debounce — chỉ emit outSearch khi nhấn Enter | [ignoreAutoComplete]="true" |
| ignoreStopPropagationEvent | boolean | false | Không gọi stopPropagation cho các DOM event bên trong | [ignoreStopPropagationEvent]="true" |
| readonly | boolean | false | Chỉ hiển thị, không cho phép nhập liệu | [readonly]="true" |
| searchConfig | IInputSearchConfig | {} | Cấu hình chi tiết giao diện ô tìm kiếm (xem bảng IInputSearchConfig) | [searchConfig]="searchConfig()" |
IInputSearchConfig
| Thuộc tính | Type | Mặc định | Mô tả | Ví dụ |
|---|---|---|---|---|
| backgroundNone | boolean | false | Xóa màu nền của ô input | backgroundNone: true |
| classContainerInput | string | '' | Class CSS bổ sung cho phần tử bọc input | classContainerInput: 'rounded-full' |
| classCoverInputSearch | string | undefined | Class CSS bổ sung cho lớp ngoài cùng của search | classCoverInputSearch: 'w-64' |
| classInclude | string | undefined | Class CSS bổ sung truyền xuống component Input | classInclude: 'border-blue-500' |
| defaultHeight | number | 32 | Chiều cao mặc định (px) của ô input | defaultHeight: 36 |
| hasClearSearch | boolean | undefined | Hiển thị nút xóa (X) khi ô có nội dung | hasClearSearch: true |
| iconLeftClass | string | 'libs-ui-icon-search' | Class icon phía trái | iconLeftClass: 'libs-ui-icon-filter' |
| iconRightClass | string | undefined | Class icon phía phải (thêm vào sau icon xóa nếu có) | iconRightClass: 'libs-ui-icon-tooltip-outline' |
| noBorder | boolean | false | Ẩn đường viền của ô input | noBorder: true |
| placeholder | string | 'i18n_search' | Placeholder của ô input (hỗ trợ i18n key) | placeholder: 'Tìm kiếm...' |
| popoverContentIconRight | string | '' | Nội dung popover hiển thị khi hover icon phải | popoverContentIconRight: 'i18n_search_hint' |
| value | string | undefined | Giá trị khởi tạo của ô tìm kiếm | value: 'từ khóa ban đầu' |
@Output()
| Output | Type | Mô tả | Handler TS | Binding HTML |
|---|---|---|---|---|
| (outFocusAndBlur) | IFocusAndBlurEvent | Emit khi ô input được focus hoặc blur, kèm trạng thái và DOM event | handlerFocusAndBlur(e: IFocusAndBlurEvent): void { e.event.stopPropagation(); this.isFocused.set(e.focus); } | (outFocusAndBlur)="handlerFocusAndBlur($event)" |
| (outFunctionsControl) | IInputFunctionControlEvent | Emit object chứa các hàm điều khiển input: focus, blur, resetValue, insertContent | handlerFunctionsControl(ctrl: IInputFunctionControlEvent): void { this.searchCtrl = ctrl; } | (outFunctionsControl)="handlerFunctionsControl($event)" |
| (outIconLeft) | string | Emit tên event khi người dùng click vào icon bên trái | handlerIconLeft(eventName: string): void { eventName; } | (outIconLeft)="handlerIconLeft($event)" |
| (outIconRight) | string | Emit tên event khi người dùng click vào icon bên phải (ngoài hành vi xóa) | handlerIconRight(eventName: string): void { eventName; } | (outIconRight)="handlerIconRight($event)" |
| (outSearch) | string | Emit chuỗi tìm kiếm (đã trim) sau debounce hoặc khi nhấn Enter. Emit '' khi người dùng xóa hết hoặc nhấn nút xóa | handlerSearch(keyword: string): void { this.loadData({ search: keyword }); } | (outSearch)="handlerSearch($event)" |
| (outValueChange) | string | Emit chuỗi ngay lập tức mỗi khi giá trị input thay đổi (mỗi keystroke) | handlerValueChange(keyword: string): void { this.currentValue.set(keyword); } | (outValueChange)="handlerValueChange($event)" |
Types & Interfaces
import {
IInputSearchConfig,
} from '@libs-ui/components-inputs-search';
// IInputFunctionControlEvent và IFocusAndBlurEvent được re-export từ:
import {
IInputFunctionControlEvent,
IFocusAndBlurEvent,
} from '@libs-ui/components-inputs-input';export interface IInputSearchConfig {
classInclude?: string; // Class CSS bổ sung cho component Input bên trong
classContainerInput?: string; // Class CSS cho phần tử bọc input
placeholder?: string; // Placeholder (hỗ trợ i18n key)
value?: string; // Giá trị khởi tạo
noBorder?: boolean; // Ẩn border
backgroundNone?: boolean; // Xóa background
iconLeftClass?: string; // Class icon trái (mặc định: 'libs-ui-icon-search')
iconRightClass?: string; // Class icon phải
defaultHeight?: number; // Chiều cao (px), mặc định: 32
classCoverInputSearch?: string; // Class cho wrapper ngoài cùng
hasClearSearch?: boolean; // Bật nút xóa nhanh (X)
popoverContentIconRight?: string; // Nội dung popover icon phải
}
export interface IInputFunctionControlEvent {
focus: (emitEvent?: boolean) => Promise<void>;
blur: (emitEvent?: boolean) => Promise<void>;
resetValue: () => Promise<void>;
insertContent: (data: string | number) => Promise<void>;
// Các method khác từ @libs-ui/components-inputs-input
}
export interface IFocusAndBlurEvent {
focus: boolean; // true = đang focus, false = đã blur
event: FocusEvent;
}Logic ẩn cần biết
Cơ chế debounce và Enter hoạt động độc lập:
- Khi người dùng gõ:
outSearchemit saudebounceTimems kể từ keystroke cuối. - Khi người dùng nhấn Enter:
outSearchemit ngay lập tức (có throttle với cùngdebounceTimeđể chống spam). - Khi người dùng nhấn Enter trong lúc debounce đang đếm: debounce bị hủy,
outSearchchỉ emit 1 lần từ luồng Enter.
Hành vi xóa nội dung (hasClearSearch: true):
- Khi ô có nội dung, icon phải tự động chuyển thành icon xóa (X).
- Nhấn X:
valueSearchreset về''vàoutSearchemit''ngay lập tức (không qua debounce). - Khi xóa hết bằng bàn phím:
outSearchemit''saudebounceTime / 2ms.
ignoreAutoComplete = true:
- Hoàn toàn vô hiệu hóa luồng debounce.
outSearchchỉ emit khi người dùng nhấn Enter.- Thích hợp cho các ô tìm kiếm cần người dùng xác nhận trước khi gửi.
Lưu ý quan trọng
⚠️ Debounce mặc định 1000ms: Nếu UX cần phản hồi nhanh hơn (ví dụ filter local), hãy giảm [debounceTime]="300" hoặc [debounceTime]="500".
⚠️ outSearch emit chuỗi rỗng khi xóa: Khi người dùng xóa hết nội dung hoặc nhấn nút X, outSearch sẽ emit ''. Handler phải xử lý trường hợp này (ví dụ: reset filter, load lại toàn bộ danh sách).
⚠️ value trong searchConfig chỉ là giá trị khởi tạo: Sau khi component khởi tạo, thay đổi searchConfig().value từ bên ngoài không tự động cập nhật giao diện. Dùng FunctionsControl.resetValue() hoặc FunctionsControl.insertContent() để cập nhật programmatically.
⚠️ outValueChange vs outSearch: Dùng outValueChange khi cần phản hồi tức thì (ví dụ: highlight từ khóa, đếm ký tự). Dùng outSearch cho các tác vụ tốn tài nguyên (gọi API).
