Skip to content

Commit

Permalink
docs: add solid filters example (#5252)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hephaestian authored Jan 3, 2024
1 parent 960513b commit 80d92d6
Show file tree
Hide file tree
Showing 12 changed files with 406 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,10 @@
"to": "examples/solid/column-visibility",
"label": "Column Visibility"
},
{
"to": "examples/solid/filters",
"label": "Filters"
},
{
"to": "examples/solid/sorting",
"label": "Sorting"
Expand Down
2 changes: 2 additions & 0 deletions examples/solid/filters/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
dist
6 changes: 6 additions & 0 deletions examples/solid/filters/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Example

To run this example:

- `npm install` or `yarn`
- `npm run start` or `yarn start`
16 changes: 16 additions & 0 deletions examples/solid/filters/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
<title>Solid App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>

<script src="/src/index.tsx" type="module"></script>
</body>
</html>
23 changes: 23 additions & 0 deletions examples/solid/filters/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "tanstack-table-example-solid-filters",
"version": "0.0.0",
"description": "",
"scripts": {
"start": "vite",
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"license": "MIT",
"devDependencies": {
"@faker-js/faker": "^8.3.1",
"typescript": "5.2.2",
"vite": "^3.2.3",
"vite-plugin-solid": "^2.2.6"
},
"dependencies": {
"@solid-primitives/scheduled": "^1.4.1",
"@tanstack/solid-table": "8.11.2",
"solid-js": "^1.6.2"
}
}
168 changes: 168 additions & 0 deletions examples/solid/filters/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import {
flexRender,
getCoreRowModel,
getFilteredRowModel,
getFacetedRowModel,
getFacetedUniqueValues,
getFacetedMinMaxValues,
ColumnDef,
ColumnFiltersState,
createSolidTable,
} from '@tanstack/solid-table'
import { debounce } from '@solid-primitives/scheduled'
import { makeData, Person } from './makeData'
import ColumnFilter from './ColumnFilter'
import { createSignal, For } from 'solid-js'


const columns: ColumnDef<Person>[] = [
{
header: 'Name',
footer: props => props.column.id,
columns: [
{
accessorKey: 'firstName',
cell: info => info.getValue(),
footer: props => props.column.id,
},
{
accessorFn: row => row.lastName,
id: 'lastName',
cell: info => info.getValue(),
header: () => <span>Last Name</span>,
footer: props => props.column.id,
},
],
},
{
header: 'Info',
footer: props => props.column.id,
columns: [
{
accessorKey: 'age',
header: () => 'Age',
footer: props => props.column.id,
},
{
header: 'More Info',
columns: [
{
accessorKey: 'visits',
header: () => <span>Visits</span>,
footer: props => props.column.id,
},
{
accessorKey: 'status',
header: 'Status',
footer: props => props.column.id,
},
{
accessorKey: 'progress',
header: 'Profile Progress',
footer: props => props.column.id,
},
],
},
],
},
]

function App() {
const [data, setData] = createSignal(makeData(50000))
const [columnFilters, setColumnFilters] = createSignal<ColumnFiltersState>([])
const [globalFilter, setGlobalFilter] = createSignal("")
const debounceSetGlobalFilter = debounce((value:string) => setGlobalFilter(value), 500)
const refreshData = () => setData(makeData(50000))

const table = createSolidTable({
get data() {
return data()
},
columns,
state: {
get columnFilters() {
return columnFilters()
},
get globalFilter() {
return globalFilter()
},
},
onGlobalFilterChange: setGlobalFilter,
globalFilterFn: "includesString",
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getFacetedRowModel: getFacetedRowModel(),
getFacetedUniqueValues: getFacetedUniqueValues(),
getFacetedMinMaxValues: getFacetedMinMaxValues(),
debugTable: true,
debugHeaders: true,
debugColumns: false,
})

return (
<div class="p-2">
<input
class="p-2 font-lg shadow border border-block"
value={globalFilter() ?? ""}
onInput={(e) => debounceSetGlobalFilter(e.currentTarget.value)}
placeholder="Search all columns..."
/>
<div className="h-2" />
<table>
<thead>
<For each={table.getHeaderGroups()}>
{headerGroup => (
<tr>
<For each={headerGroup.headers}>
{header => (
<th colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getCanFilter() ? (
<div>
<ColumnFilter column={header.column} table={table} />
</div>
) : null}
</>
)}
</th>
)}
</For>
</tr>
)}
</For>
</thead>
<tbody>
<For each={table.getRowModel().rows.slice(0, 10)}>
{row => (
<tr>
<For each={row.getVisibleCells()}>
{cell => (
<td>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</td>
)}
</For>
</tr>
)}
</For>
</tbody>
</table>
<div>{table.getRowModel().rows.length} Rows</div>
<div>
<button onClick={() => refreshData()}>Refresh Data</button>
</div>
<pre>{JSON.stringify(table.getState(), null, 2)}</pre>
</div>
)
}

export default App
83 changes: 83 additions & 0 deletions examples/solid/filters/src/ColumnFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
Column,
Table,
} from '@tanstack/solid-table'
import { debounce } from '@solid-primitives/scheduled'
import { createMemo } from 'solid-js'

function ColumnFilter({
column,
table,
}: {
column: Column<any, unknown>
table: Table<any>
}) {
const firstValue = table
.getPreFilteredRowModel()
.flatRows[0]?.getValue(column.id)

const columnFilterValue = column.getFilterValue()

const sortedUniqueValues = createMemo(
() =>
typeof firstValue === 'number'
? []
: Array.from(column.getFacetedUniqueValues().keys()).sort(),
[column.getFacetedUniqueValues()]
)

const debounceColumnFilter = debounce(value => column.setFilterValue(value), 500)

return typeof firstValue === 'number' ? (
<div>
<div className="flex space-x-2">
<input
type="number"
min={Number(column.getFacetedMinMaxValues()?.[0] ?? '')}
max={Number(column.getFacetedMinMaxValues()?.[1] ?? '')}
value={(columnFilterValue as [number, number])?.[0] ?? ''}
onInput={(e) => debounceColumnFilter((old: [number, number]) => [e.target.value, old?.[1]])}
placeholder={`Min ${
column.getFacetedMinMaxValues()?.[0]
? `(${column.getFacetedMinMaxValues()?.[0]})`
: ''
}`}
className="w-24 border shadow rounded"
/>
<input
type="number"
min={Number(column.getFacetedMinMaxValues()?.[0] ?? '')}
max={Number(column.getFacetedMinMaxValues()?.[1] ?? '')}
value={(columnFilterValue as [number, number])?.[1] ?? ''}
onInput={(e) => debounceColumnFilter((old: [number, number]) => [old?.[0], e.target.value])}
placeholder={`Max ${
column.getFacetedMinMaxValues()?.[1]
? `(${column.getFacetedMinMaxValues()?.[1]})`
: ''
}`}
className="w-24 border shadow rounded"
/>
</div>
<div className="h-1" />
</div>
) : (
<>
<datalist id={column.id + 'list'}>
{sortedUniqueValues().slice(0, 5000).map((value: any) => (
<option value={value} key={value} />
))}
</datalist>
<input
type="text"
value={(columnFilterValue ?? '') as string}
onInput={(e) => debounceColumnFilter(e.target.value)}
placeholder={`Search... (${column.getFacetedUniqueValues().size})`}
className="w-36 border shadow rounded"
list={column.id + 'list'}
/>
<div className="h-1" />
</>
)
}

export default ColumnFilter
26 changes: 26 additions & 0 deletions examples/solid/filters/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
html {
font-family: sans-serif;
font-size: 14px;
}

table {
border: 1px solid lightgray;
}

tbody {
border-bottom: 1px solid lightgray;
}

th {
border-bottom: 1px solid lightgray;
border-right: 1px solid lightgray;
padding: 2px 4px;
}

tfoot {
color: gray;
}

tfoot th {
font-weight: normal;
}
7 changes: 7 additions & 0 deletions examples/solid/filters/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/* @refresh reload */
import { render } from 'solid-js/web'

import './index.css'
import App from './App'

render(() => <App />, document.getElementById('root') as HTMLElement)
Loading

0 comments on commit 80d92d6

Please sign in to comment.