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-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 ISort kèm hàm reset().

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ểu ISort kèm hàm reset() để 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-sort

Import

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ù onlyEmittrue 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ường modeNumber tiện dụng khi gửi tham số số lên API (1 = asc, 2 = desc). Hàm reset() đư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 ignorePopoverContenttrue (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).