@@ -22,6 +22,57 @@ import { Button } from '@/afcl'
2222```
2323
2424``` html
25+
26+ ### Sorting
27+
28+ Table supports column sorting out of the box.
29+
30+ - Sorting is enabled globally by default. You can disable it entirely with `:sortable="false"`.
31+ - Per column, sorting can be disabled with `sortable: false` inside the column definition.
32+ - Clicking a sortable header cycles sorting in a tri‑state order:
33+ - none → ascending → descending → none
34+ - When it returns to "none", the sorting is cleared.
35+
36+ Basic example (client-side sorting when `data` is an array):
37+
38+ ```html
39+ <Table
40+ :columns =" [
41+ { label: 'Name', fieldName: 'name' },
42+ { label: 'Age', fieldName: 'age' },
43+ // disable sort for a specific column
44+ { label: 'Country', fieldName: 'country', sortable: false },
45+ ]"
46+ :data =" [
47+ { name: 'John', age: 30, country: 'US' },
48+ { name: 'Rick', age: 25, country: 'CA' },
49+ { name: 'Alice', age: 35, country: 'BR' },
50+ { name: 'Colin', age: 40, country: 'AU' },
51+ ]"
52+ :sortable =" true"
53+ :pageSize =" 3"
54+ />
55+ ```
56+
57+ You can also predefine a default sort:
58+
59+ ``` html
60+ <Table
61+ :columns =" [
62+ { label: 'Name', fieldName: 'name' },
63+ { label: 'Age', fieldName: 'age' },
64+ { label: 'Country', fieldName: 'country' },
65+ ]"
66+ :data =" rows"
67+ defaultSortField =" age"
68+ defaultSortDirection =" desc"
69+ />
70+ ```
71+
72+ Notes:
73+ - Client-side sorting supports nested field paths using dot-notation, e.g. ` user.name ` .
74+ - When a column is not currently sorted, a subtle double-arrow icon is shown; arrows switch up/down for ascending/descending.
75+
2576<Button @click ="doSmth"
2677 : loader ="false" class="w-full">
2778 Your button text
@@ -973,6 +1024,59 @@ async function loadPageData(data) {
9731024```
9741025> 👆 The page size is used as the limit for pagination.
9751026
1027+ ### Server-side sorting
1028+
1029+ When you provide an async function to ` data ` , the table will pass the current sort along with pagination params.
1030+
1031+ Signature of the loader receives:
1032+
1033+ ``` ts
1034+ type LoaderArgs = {
1035+ offset: number ;
1036+ limit: number ;
1037+ sortField? : string ; // undefined when unsorted
1038+ sortDirection? : ' asc' | ' desc' ; // only when sortField is set
1039+ }
1040+ ` ` `
1041+
1042+ Example using ` fetch ` :
1043+
1044+ ` ` ` ts
1045+ async function loadPageData({ offset , limit , sortField , sortDirection }) {
1046+ const url = new URL (' /api/products' , window .location .origin );
1047+ url .searchParams .set (' offset' , String (offset ));
1048+ url .searchParams .set (' limit' , String (limit ));
1049+ if (sortField ) url .searchParams .set (' sortField' , sortField );
1050+ if (sortField && sortDirection ) url .searchParams .set (' sortDirection' , sortDirection );
1051+
1052+ const res = await fetch (url .toString (), { credentials: ' include' });
1053+ const json = await res .json ();
1054+ return { data: json .data , total: json .total };
1055+ }
1056+
1057+ < Table
1058+ :columns = " [
1059+ { label : ' ID' , fieldName : ' id' },
1060+ { label : ' Title' , fieldName : ' title' },
1061+ { label : ' Price' , fieldName : ' price' },
1062+ ]"
1063+ :data=" loadPageData "
1064+ :pageSize=" 10 "
1065+ />
1066+ ```
1067+
1068+ Events you can listen to:
1069+
1070+ ``` html
1071+ <Table
1072+ :columns =" columns"
1073+ :data =" loadPageData"
1074+ @update:sortField =" (f) => currentSortField = f"
1075+ @update:sortDirection =" (d) => currentSortDirection = d"
1076+ @sort-change =" ({ field, direction }) => console.log('sort changed', field, direction)"
1077+ />
1078+ ```
1079+
9761080### Table loading states
9771081
9781082For tables where you load data externally and pass them to ` data ` prop as array (including case with front-end pagination) you might want to show skeleton loaders in table externaly using ` isLoading ` props.
0 commit comments