Table
The Table
component is used to display tabular formatted data appropriately.
Examples
Name | Weapon | Grand Slams | Birthdate |
---|---|---|---|
Roger Federer | Forehand and serve | 20π | August 8, 1981 |
Andre Agassi | Return of serve. Groundstrokes | 8π | April 29, 1970 |
Steffi Graf | Forehand | 22π | June 14, 1969 |
Martina Navratilova | Serve and volley | 18π | October 18, 1956 |
Rafael Nadal | Backhand and speed | 20π | June 3, 1986 |
Althea Gibson | Speed, strength, and fluidity | 11π | August 25, 1927 |
Novak Djokovic | Backhand and speed | 20π | May 22, 1987 |
Arthur Ashe | Serve and volley | 3π | July 10, 1943 |
Please note! You need to ensure the length of your table headers and the length of each row's columns are equivalent. If not, expect undefined behavior.
We typically see this happen if one splices the headers but not the rows.
Usage
React
View source
import "agnostic-react/dist/common.min.css";
import "agnostic-react/dist/esm/index.css";
import { Table } from "agnostic-react";
const headersWithWidths = [
{
label: 'Name',
key: 'name',
width: '25%',
sortable: true,
},
{
label: 'Weapon',
key: 'weapon',
width: '45%',
},
{
label: 'Grand Slams',
key: 'slams',
width: '13%',
sortable: true,
renderFn: (key, value) => (
<td key={key} style={{ textAlign: 'center' }}>
{value}
<span className="mis6">π</span>
</td>
),
},
{
label: 'Birthdate',
key: 'birthdate',
width: '17%',
sortable: true,
sortFn: (a, b) => {
const d1 = new Date(a).getTime() || -Infinity;
const d2 = new Date(b).getTime() || -Infinity;
if (d1 > d2) {
return 1;
}
if (d1 < d2) {
return -1;
}
return 0;
},
},
];
const createRow = (name, weapon, slams, birthdate) => ({ name, weapon, slams, birthdate });
const rows = [
createRow(
'Serena Williams',
"Biggest serve in women's tennis all-time",
23,
'September 26, 1981',
),
createRow('Roger Federer', 'Forehand and serve', 20, 'August 8, 1981'),
createRow('Andre Agassi', 'Return of serve. Groundstrokes', 8, 'April 29, 1970'),
createRow('Steffi Graf', 'Forehand', 22, 'June 14, 1969')
];
export const YourComponent = () => (
<section className="mbe24">
<Table
headers={headersWithWidths}
rows={rows}
isStriped
caption="Tennis Superstars"
/>
</section>
);
React: component source, storybook tests
Vue 3
View source
<template>
<section class="mbe40">
<div class="h4 mbe32 flex items-center">
<img
width="24"
height="24"
src="/assets/Vue-icon.svg"
alt="Vue logo"
class="mie12"
/>Vue 3 Close
</div>
<Table
:rows="rows"
:headers="headers"
:isHoverable="true"
caption="My caption test"
/>
</section>
</template>
<script setup>
// Components CSS
import "agnostic-vue/dist/index.css";
import { Table } from "agnostic-vue";
const createRow = (name, weapon, slams, birthdate) => ({
name,
weapon,
slams,
birthdate,
});
const rows = [
createRow("Roger Federer", "Forehand and serve", 20, "August 8, 1981"),
createRow(
"Andre Agassi",
"Return of serve. Groundstrokes",
8,
"April 29, 1970"
),
createRow("Steffi Graf", "Forehand", 22, "June 14, 1969"),
createRow("Martina Navratilova", "Serve and volley", 18, "October 18, 1956"),
createRow("Rafael Nadal", "Backhand and speed", 20, "June 3, 1986"),
createRow(
"Althea Gibson",
"Speed, strength, and fluidity ",
11,
"August 25, 1927"
),
createRow("Novak Djokovic", "Backhand and speed", 20, "May 22, 1987"),
createRow("Arthur Ashe", "Serve and volley", 3, "July 10, 1943"),
];
const headers = [
{
label: "Name",
key: "name",
width: "25%",
sortable: true,
},
{
label: "Weapon",
key: "weapon",
width: "35%",
},
{
label: "Grand Slams",
key: "slams",
width: "13%",
sortable: true,
// Only use this approach for trusted input that you control
renderFn: (value) =>
`<div class="text-center">${value}<span class="mis6">π</span></div>`,
},
{
label: "Birthdate",
key: "birthdate",
sortable: true,
sortFn: (a, b) => {
// Naive date comparisons; but we're controlling data so ;-)
const d1 = new Date(a).getTime() || -Infinity;
const d2 = new Date(b).getTime() || -Infinity;
if (d1 > d2) {
return 1;
}
if (d1 < d2) {
return -1;
}
return 0;
},
},
];
</script>
Vue 3: component source, storybook tests
Svelte
View source
<script>
import 'agnostic-svelte/css/common.min.css';
import { Table } from "agnostic-svelte";
import CustomCellRenderer from "path/to/CustomCellRenderer.svelte";
const createRow = (name, weapon, slams, birthdate) => ({
name,
weapon,
slams,
birthdate,
});
const tableArgs = {
rows: [
createRow("Roger Federer", "Forehand and serve", 20, "August 8, 1981"),
createRow(
"Andre Agassi",
"Return of serve. Groundstrokes",
8,
"April 29, 1970"
),
createRow("Steffi Graf", "Forehand", 22, "June 14, 1969"),
createRow(
"Martina Navratilova",
"Serve and volley",
18,
"October 18, 1956"
),
createRow("Rafael Nadal", "Backhand and speed", 20, "June 3, 1986"),
createRow(
"Althea Gibson",
"Speed, strength, and fluidity ",
11,
"August 25, 1927"
),
createRow("Novak Djokovic", "Backhand and speed", 20, "May 22, 1987"),
createRow("Arthur Ashe", "Serve and volley", 3, "July 10, 1943"),
],
headers: [
{
label: 'Name',
key: 'name',
width: '25%',
sortable: true,
},
{
label: 'Weapon',
key: 'weapon',
width: '45%',
},
{
label: 'Grand Slams',
key: 'slams',
width: '10%',
sortable: true,
renderComponent: () => CustomCellRenderer
},
{
label: "Birthdate",
key: "birthdate",
width: '20%',
sortable: true,
sortFn: (a, b) => {
const d1 = new Date(a).getTime() || -Infinity;
const d2 = new Date(b).getTime() || -Infinity;
if (d1 > d2) {
return 1;
}
if (d1 < d2) {
return -1;
}
return 0;
},
},
],
caption: "Tennis Superstars",
}
</script>
<Table {...tableArgs} />
The CustomCellRenderer.svelte
used in the above example simply renders the Grand Slams columns:
<script>
export let cellValue;
</script>
<td>{cellValue}<span class="mis6">π</span></td>
Svelte: component source, storybook tests
Angular (Experimental)
View source
In your Angular configuration (likely angular.json
) ensure you're including the common AgnosticUI styles:
"styles": ["agnostic-angular/common.min.css"],
Add AgnosticUI's AgModule
module:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AgModule } from 'agnostic-angular';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AgModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
Now you can use in your components:
import { Component } from '@angular/core';
@Component({
selector: 'your-component',
template: `<section>
<ag-table [headers]="[ { label: 'Name', key: 'name', width: '85%', sortable: true }, { label: 'Grand Slams', key: 'slams', width: '15%', sortable: true }]"
[rows]="[{ name: 'Serena Williams', slams: 23}, { name: 'Roger Federer', slams: 20}, { name: 'Althea Gibson', slams: 11}, { name: 'Andre Agassi', slams: 8}]"
[rowRenderTemplate]="rowRenderTemplate"
[isHoverable]="true"
caption="Tennis Superstars">
<ng-template #rowRenderTemplate
let-row
let-idx="index">
<div *ngIf="idx === 1; else simple">{{row}}<span class="mis6">π</span></div>
<ng-template #simple>
{{row}}
</ng-template>
</ng-template>
</ag-table>
</section>`
})
export class YourComponent {}
Angular: component source, storybook tests
Storybook
You can run the framework Storybooks and see live examples for React, Vue 3, Svelte, Astro, and Angular (experimental). The following will set up Storybook and run locally:
How to run Storybook
git clone git@github.com:AgnosticUI/agnosticui.git
cd agnosticui/<PACKAGE_NAME> && npm i # e.g. cd agnosticui/agnostic-react && npm i
npm run storybook
See Running Storybook.