@libs-ui/components-buttons-sort
v0.2.357-11
Published
> Component nút sort asc/desc gọn nhẹ, hỗ trợ two-way binding, disable từng chiều và emit payload `ISort` kèm hàm `reset()`.
Readme
@libs-ui/components-buttons-sort
Component nút sort asc/desc gọn nhẹ, hỗ trợ two-way binding, disable từng chiều và emit payload
ISortkèm hàmreset().
Giới thiệu
Package @libs-ui/components-buttons-sort cung cấp 2 component sắp xếp dữ liệu cho bảng và danh sách. LibsUiComponentsButtonsSortComponent hiển thị 2 nút riêng biệt cho chiều tăng dần (asc) và giảm dần (desc). LibsUiComponentsButtonsSortArrowComponent là kiểu toggle 1 nút mũi tên chuyển đổi giữa asc và desc, tích hợp thêm popover mô tả trạng thái hiện tại.
Tính năng
- ✅ Hai kiểu UI: Sort (2 nút riêng) và Arrow (1 nút toggle)
- ✅ Two-way binding qua
[(mode)]— đồng bộ trạng thái với component cha - ✅ Emit payload
(outChange)kiểuISortkèm hàmreset()để xóa sort - ✅ Disable toàn bộ (
[disable]) hoặc disable từng chiều ([disableAsc],[disableDesc]) - ✅
[onlyEmit]— luôn emit event kể cả khi click vào chiều đang active - ✅ Arrow hỗ trợ
[defaultMode]— chiều sort mặc định khi click lần đầu - ✅ Arrow hỗ trợ popover mô tả asc/desc (
[popoverContentAsc],[popoverContentDesc]) - ✅ Tùy chỉnh kích thước icon qua
[size] - ✅ Standalone component + OnPush Change Detection + Angular Signals
Khi nào sử dụng
- Khi cần UI sort asc/desc cho cột trong bảng dữ liệu
- Khi cần binding trạng thái sort qua
[(mode)]để đồng bộ với state bên ngoài - Khi cần disable toàn bộ sort hoặc disable riêng từng chiều (chỉ cho phép sắp xếp 1 chiều)
- Khi muốn sort button luôn emit event mà không bị chặn khi click lại chiều đang active (
onlyEmit) - Khi cần kiểu toggle 1 nút (Arrow) với popover giải thích ý nghĩa asc/desc cho người dùng
Cài đặt
npm install @libs-ui/components-buttons-sortImport
import {
LibsUiComponentsButtonsSortComponent,
LibsUiComponentsButtonsSortArrowComponent,
ISort,
TYPE_SORT_TYPE,
} from '@libs-ui/components-buttons-sort';Ví dụ sử dụng
1. Sort cơ bản — 2 nút asc/desc
example.component.html
<libs_ui-components-buttons-sort
[fieldSort]="'name'"
[(mode)]="sortMode"
(outChange)="handlerSortChange($event)"
/>example.component.ts
import { Component, signal } from '@angular/core';
import {
LibsUiComponentsButtonsSortComponent,
ISort,
TYPE_SORT_TYPE,
} from '@libs-ui/components-buttons-sort';
@Component({
selector: 'app-example',
standalone: true,
imports: [LibsUiComponentsButtonsSortComponent],
templateUrl: './example.component.html',
})
export class ExampleComponent {
readonly sortMode = signal<TYPE_SORT_TYPE>('');
handlerSortChange(sort: ISort): void {
console.log(sort.mode, sort.fieldSort, sort.modeNumber);
// Gọi sort.reset() để đưa mode về '' khi cần xóa sort
}
}2. Sort với custom size và disable chiều asc
example.component.html
<libs_ui-components-buttons-sort
[size]="14"
[disableAsc]="true"
[fieldSort]="'createdAt'"
[(mode)]="sortMode"
(outChange)="handlerSortChange($event)"
/>example.component.ts
import { Component, signal } from '@angular/core';
import {
LibsUiComponentsButtonsSortComponent,
ISort,
TYPE_SORT_TYPE,
} from '@libs-ui/components-buttons-sort';
@Component({
selector: 'app-example-size',
standalone: true,
imports: [LibsUiComponentsButtonsSortComponent],
templateUrl: './example.component.html',
})
export class ExampleSizeComponent {
readonly sortMode = signal<TYPE_SORT_TYPE>('');
handlerSortChange(sort: ISort): void {
console.log('sort changed', sort);
}
}3. Arrow toggle — 1 nút với popover
example.component.html
<libs_ui-components-buttons-sort-arrow
[fieldSort]="'name'"
[ignorePopoverContent]="false"
[popoverContentAsc]="'Sắp xếp tăng dần (A → Z)'"
[popoverContentDesc]="'Sắp xếp giảm dần (Z → A)'"
[defaultMode]="'asc'"
[(mode)]="arrowMode"
(outChange)="handlerArrowChange($event)"
/>example.component.ts
import { Component, signal } from '@angular/core';
import {
LibsUiComponentsButtonsSortArrowComponent,
ISort,
TYPE_SORT_TYPE,
} from '@libs-ui/components-buttons-sort';
@Component({
selector: 'app-example-arrow',
standalone: true,
imports: [LibsUiComponentsButtonsSortArrowComponent],
templateUrl: './example.component.html',
})
export class ExampleArrowComponent {
readonly arrowMode = signal<TYPE_SORT_TYPE>('');
handlerArrowChange(sort: ISort): void {
console.log('arrow sort changed', sort.mode, sort.fieldSort);
}
}4. Sort disable toàn bộ
<libs_ui-components-buttons-sort
[disable]="true"
[fieldSort]="'status'"
[(mode)]="sortMode"
/>5. Sort với onlyEmit — luôn emit dù click lại chiều đang active
<libs_ui-components-buttons-sort
[onlyEmit]="true"
[fieldSort]="'name'"
[(mode)]="sortMode"
(outChange)="handlerSortChange($event)"
/>@Input() — libs_ui-components-buttons-sort
| Input | Type | Default | Mô tả | Ví dụ |
|---|---|---|---|---|
| [disable] | boolean | false | Disable toàn bộ sort button, không thể click cả 2 chiều | [disable]="true" |
| [disableAsc] | boolean | false | Disable riêng chiều tăng dần (asc) | [disableAsc]="true" |
| [disableDesc] | boolean | false | Disable riêng chiều giảm dần (desc) | [disableDesc]="true" |
| [fieldSort] | string | '' | Tên field đang sort — được trả về nguyên vẹn trong payload ISort.fieldSort | [fieldSort]="'name'" |
| [(mode)] | TYPE_SORT_TYPE | '' | Two-way binding mode sort hiện tại: 'asc' / 'desc' / '' (không sort) | [(mode)]="sortMode" |
| [onlyEmit] | boolean | false | Cấu hình dự kiến: khi true sẽ vẫn emit event kể cả khi click lại chiều đang active. Lưu ý: ở bản hiện tại, component luôn emit dù onlyEmit là true hay false (xem mục Lưu ý quan trọng) | [onlyEmit]="true" |
| [size] | number | 10 | Kích thước icon sort theo đơn vị px | [size]="14" |
@Output() — libs_ui-components-buttons-sort
| Output | Type | Mô tả | Handler TS | Binding HTML |
|---|---|---|---|---|
| (outChange) | ISort | Emit khi người dùng click 1 trong 2 nút sort, trả về object ISort gồm mode, modeNumber, fieldSort và hàm reset() | handlerSortChange(sort: ISort): void { sort.reset; console.log(sort); } | (outChange)="handlerSortChange($event)" |
@Input() — libs_ui-components-buttons-sort-arrow (Sub-component)
| Input | Type | Default | Mô tả | Ví dụ |
|---|---|---|---|---|
| [defaultMode] | TYPE_SORT_TYPE | '' | Mode sort mặc định khi người dùng click lần đầu (khi mode hiện tại đang rỗng) | [defaultMode]="'asc'" |
| [disable] | boolean | false | Disable sort arrow button, không thể click | [disable]="true" |
| [fieldSort] | string | '' | Tên field đang sort — được trả về nguyên vẹn trong payload ISort.fieldSort | [fieldSort]="'name'" |
| [ignorePopoverContent] | boolean | true | Khi false: hiển thị popover khi hover, cần truyền popoverContentAsc/popoverContentDesc | [ignorePopoverContent]="false" |
| [(mode)] | TYPE_SORT_TYPE | '' | Two-way binding mode sort hiện tại: 'asc' / 'desc' / '' | [(mode)]="arrowMode" |
| [popoverContentAsc] | string \| undefined | undefined | Nội dung text hiển thị trong popover khi mode đang là asc | [popoverContentAsc]="'Sắp xếp A → Z'" |
| [popoverContentDesc] | string \| undefined | undefined | Nội dung text hiển thị trong popover khi mode đang là desc | [popoverContentDesc]="'Sắp xếp Z → A'" |
| [size] | number | 16 | Kích thước icon mũi tên theo đơn vị px | [size]="20" |
| [zIndex] | number | 10 | z-index của popover overlay | [zIndex]="100" |
@Output() — libs_ui-components-buttons-sort-arrow (Sub-component)
| Output | Type | Mô tả | Handler TS | Binding HTML |
|---|---|---|---|---|
| (outChange) | ISort | Emit khi người dùng click nút arrow, trả về object ISort gồm mode, modeNumber, fieldSort và hàm reset() | handlerArrowChange(sort: ISort): void { console.log(sort.mode); } | (outChange)="handlerArrowChange($event)" |
Types & Interfaces
import { ISort, TYPE_SORT_TYPE } from '@libs-ui/components-buttons-sort';
// Kiểu mode sort
export type TYPE_SORT_TYPE = 'asc' | 'desc' | '';
// Payload emit ra khi sort thay đổi
export interface ISort {
mode: TYPE_SORT_TYPE; // Chiều sort hiện tại: 'asc' | 'desc' | ''
modeNumber: 1 | 2; // 1 = asc, 2 = desc
fieldSort: string; // Tên field đang sort (từ input [fieldSort])
reset: () => void; // Gọi để reset mode về '' (xóa sort)
}Mô tả
TYPE_SORT_TYPE: Union type cho trạng thái sort. Giá trị''(chuỗi rỗng) biểu thị không có sort nào đang active.ISort: Object được emit qua(outChange). TrườngmodeNumbertiện dụng khi gửi tham số số lên API (1= asc,2= desc). Hàmreset()đưa mode về''— có thể gọi trực tiếp từ payload:sort.reset().
Lưu ý quan trọng
⚠️ Two-way binding với signal: Khi dùng [(mode)] cùng Angular Signal, phải truyền giá trị signal đã gọi (): [(mode)]="sortMode()" trong inline template hoặc khai báo biến readonly sortMode = signal<TYPE_SORT_TYPE>('') và dùng [(mode)]="sortMode" trong template file riêng — Angular sẽ tự xử lý.
⚠️ onlyEmit hiện luôn có hiệu lực như true: Do cách kiểm tra điều kiện nội bộ, ở bản hiện tại libs_ui-components-buttons-sort luôn emit (outChange) khi click — kể cả khi click lại đúng chiều đang active và [onlyEmit] không được truyền (mặc định false). Input [onlyEmit] hiện chưa tạo ra khác biệt hành vi. Logic disableAsc/disableDesc vẫn hoạt động độc lập — click vào chiều bị disable sẽ không emit.
⚠️ Arrow popover cần ignorePopoverContent="false": Mặc định ignorePopoverContent là true (bỏ qua popover). Phải đặt [ignorePopoverContent]="false" mới kích hoạt popover — đồng thời cần truyền popoverContentAsc hoặc popoverContentDesc để có nội dung hiển thị.
⚠️ reset() trong ISort: Hàm reset() được bind vào instance component — gọi sort.reset() sẽ đặt lại mode về '' trực tiếp trên component gốc. Dùng khi cần reset sort từ bên ngoài (vd: clear filter).
