Sort data in a table
interface User {
firstName: string;
lastName: string;
age: number;
}
const [users, setUsers] = useState<User[]>([]);
useEffect(() => {
const _users: User[] = [
{ firstName: "Christian", lastName: "Batz", age: 18 },
{ firstName: "Brain", lastName: "Wisozk", age: 19 },
{ firstName: "Neha", lastName: "Jones", age: 23 },
{ firstName: "Tristin", lastName: "Buckridge", age: 31 },
];
setUsers(_users);
}, []);
function sortData(event: GoabTableOnSortDetail) {
const _users = [...users];
_users.sort((a: any, b: any) => {<GoabxTable onSort={sortData} width="100%">
<thead>
<tr>
<th>
<GoabxTableSortHeader name="firstName">First name</GoabxTableSortHeader>
</th>
<th>
<GoabxTableSortHeader name="lastName">Last name</GoabxTableSortHeader>
</th>
<th>
<GoabxTableSortHeader name="age" direction="asc">
Age
</GoabxTableSortHeader>
</th>
</tr>
</thead>
<tbody>
{users.map((user) => (
<tr key={user.firstName}>
<td>{user.firstName}</td>
<td>{user.lastName}</td>
<td>{user.age}</td>
</tr>
))}
</tbody>
</GoabxTable>users: User[] = [
{ firstName: "Christian", lastName: "Batz", age: 18 },
{ firstName: "Brain", lastName: "Wisozk", age: 19 },
{ firstName: "Neha", lastName: "Jones", age: 23 },
{ firstName: "Tristin", lastName: "Buckridge", age: 31 },
];
handleSort(event: GoabTableOnSortDetail): void {
const { sortBy, sortDir } = event;
this.users.sort(
(a: any, b: any) => (a[sortBy] > b[sortBy] ? 1 : -1) * sortDir
);
}<goabx-table width="100%" mb="xl" (onSort)="handleSort($event)">
<thead>
<tr>
<th>
<goab-table-sort-header name="firstName">First name</goab-table-sort-header>
</th>
<th>
<goab-table-sort-header name="lastName">Last name</goab-table-sort-header>
</th>
<th>
<goab-table-sort-header name="age" direction="asc">Age</goab-table-sort-header>
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let user of users">
<td>{{ user.firstName }}</td>
<td>{{ user.lastName }}</td>
<td>{{ user.age }}</td>
</tr>
</tbody>
</goabx-table>let users = [
{ firstName: "Christian", lastName: "Batz", age: 18 },
{ firstName: "Brain", lastName: "Wisozk", age: 19 },
{ firstName: "Neha", lastName: "Jones", age: 23 },
{ firstName: "Tristin", lastName: "Buckridge", age: 31 },
];
const tbody = document.getElementById("table-body");
let sortColumn = "age";
let sortDirection = 1; // 1 = asc, -1 = desc
function renderTable() {
tbody.innerHTML = "";
users.forEach((user) => {
const row = document.createElement("tr");
row.innerHTML = `
<td>${user.firstName}</td>
<td>${user.lastName}</td>
<td>${user.age}</td>
`;
tbody.appendChild(row);
});
}
function sortTable(column) {
// Toggle direction if same column, otherwise start ascending
if (column === sortColumn) {
sortDirection = sortDirection * -1;
} else {
sortColumn = column;
sortDirection = 1;
}
// Update header visual states
document.querySelectorAll("goa-table-sort-header").forEach((header) => {
const name = header.getAttribute("name");
if (name === sortColumn) {
header.setAttribute("direction", sortDirection === 1 ? "asc" : "desc");
} else {
header.setAttribute("direction", "none");
}
});
// Sort the data
users.sort((a, b) => (a[sortColumn] > b[sortColumn] ? 1 : -1) * sortDirection);
renderTable();
}
// Attach click handlers directly to sort headers
// (Table's built-in slot-based wiring doesn't work with innerHTML)
document.querySelectorAll("goa-table-sort-header").forEach((header) => {
header.addEventListener("click", () => {
const column = header.getAttribute("name");
sortTable(column);
});
});
// Initial sort by age ascending
users.sort((a, b) => (a.age > b.age ? 1 : -1));
renderTable();<goa-table version="2" width="100%" mb="xl">
<table width="100%">
<thead>
<tr>
<th>
<goa-table-sort-header name="firstName">First name</goa-table-sort-header>
</th>
<th>
<goa-table-sort-header name="lastName">Last name</goa-table-sort-header>
</th>
<th>
<goa-table-sort-header name="age" direction="asc">Age</goa-table-sort-header>
</th>
</tr>
</thead>
<tbody id="table-body"></tbody>
</table>
</goa-table>Enable column sorting in tables using sort headers, allowing workers to organize data by clicking column headers to toggle ascending/descending order.
When to use
Use this pattern when:
- Workers need to organize tabular data by different columns
- Data sets are large enough that sorting improves usability
- Multiple columns could reasonably be used as sort criteria
Considerations
- Indicate the current sort direction with visual cues
- Set a sensible default sort order when the table loads
- Consider which columns should be sortable based on data type
- Numeric columns typically sort numerically, text columns alphabetically
- Maintain sort state when data updates if appropriate