Skip to main content
Partas

Render the Table

Let's put it all together and render our first basic table before adding more elements.

TableTest.fs
module Partas.Solid.Example.TableTest
open Partas.Solid
open Partas.Solid.Example.TestColumnDefs
open Partas.Solid.TanStack.Table
open Fable.Core
let userData = [|
{ Name = "Name"; Color = "Color"; Code = "Code" }
{ Name = "Name1"; Color = "Color1"; Code = "Code1" }
{ Name = "Name2"; Color = "Color2"; Code = "Code2" }
|]
[<SolidComponent>]
let Test () =
let table = createTable(
TableOptions<User>(
getCoreRowModel = getCoreRowModel()
) .data(fun _ -> userData)
.columns(fun _ -> columnDefs)
)
DataTable(table = table)
Why are data & columns methods?

TanStack requires the data and columns to be get properties of the TableOptions object passed to createTable.

The .data and .columns method take care of this for you.

CodeNameColor
Code
Name
Color
Code1
Name1
Color1
Code2
Name2
Color2
All example code
module Partas.Solid.examples.datatable
open Partas.Solid
open Fable.Core
open Fable.Core.JsInterop
open Partas.Solid.TanStack.Table
importSideEffects "~/app.css"
type [<Erase>] Lib =
[<Import("twMerge", "tailwind-merge")>]
static member twMerge (classes: string) : string = jsNative
[<Import("clsx", "clsx")>]
static member clsx(classes: obj): string = jsNative
static member cn (classes: string array): string = classes |> Lib.clsx |> Lib.twMerge
[<Erase>]
type TableCaption() =
inherit caption()
[<SolidTypeComponent>]
member props.__ =
caption(class' = Lib.cn [|
"mt-4 text-sm text-muted-foreground"
props.class'
|]).spread props
[<Erase>]
type Table() =
inherit table()
[<SolidTypeComponent>]
member props.__ =
div(class' = "relative w-full overflow-auto") {
table(class' = Lib.cn [|
"w-full caption-bottom text-sm"
props.class'
|]).spread props
}
[<Erase>]
type TableHeader() =
inherit thead()
[<SolidTypeComponent>]
member props.constructor =
thead(class' = Lib.cn [| "[&_tr]:border-b"
props.class' |])
.spread props
[<Erase>]
type TableBody() =
inherit tbody()
[<SolidTypeComponent>]
member props.constructor =
tbody(class' = Lib.cn [|
"[&_tr:last-child]:border-0"
props.class'
|]).spread props
[<Erase>]
type TableFooter() =
inherit tfoot()
[<SolidTypeComponent>]
member props.constructor =
tfoot(class' = Lib.cn [|
"bg-primary font-medium text-primary-foreground"
props.class'
|]).spread props
[<Erase>]
type TableRow() =
inherit tr()
[<SolidTypeComponent>]
member props.constructor =
tr(
class' = Lib.cn [|
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted"
props.class'
|]
).spread props
[<Erase>]
type TableHead() =
inherit th()
[<SolidTypeComponent>]
member props.constructor =
th(
class' = Lib.cn [|
"h-10 px-2 text-left align-middle font-medium
text-muted-foreground [&:has([role=checkbox])]:pr-0"
props.class'
|]
).spread props
[<Erase>]
type TableCell() =
inherit td()
[<SolidTypeComponentAttribute>]
member props.constructor =
td(class' = Lib.cn [| "p-2 align-middle [&:has([role=checkbox])]:pr-0"; props.class' |]).spread props
[<Erase>]
type DataTable<'T>() =
interface VoidNode
[<DefaultValue>] val mutable table: Table<'T>
[<SolidTypeComponent>]
member props.__ =
let table = props.table
Table() {
TableHeader() {
For(each = table.getHeaderGroups()) {
yield fun headerGroup _ ->
TableRow() {
For(each = headerGroup.headers) {
yield fun header _ ->
TableHead(colspan = header.colSpan) {
Show(when' = not header.isPlaceholder) {
flexRender(header.column.columnDef.header, header.getContext())
}
}
}
}
}
}
TableBody() {
Show(
when' = unbox (table.getRowModel().rows.Length)
,fallback = (TableRow() { TableCell(colspan = (8), class' = "h-24 text-center") { "No Results." } })
) {
For(each = table.getRowModel().rows) {
yield fun row _ ->
TableRow().data("state", !!(row.getIsSelected() && !!"selected")) {
For(each = row.getVisibleCells()) {
yield fun cell _ ->
TableCell() {
flexRender(cell.column.columnDef.cell, cell.getContext())
}
}
}
}
}
}
}
type User = {
Code: string
Name: string
Color: string
}
[<SolidComponent>]
let codeColumn = ColumnDef<User>(
accessorFn = fun user _ -> user.Code
,header = !!"Code"
,cell = fun props ->
div(class' = "w-14 hover:scale-102 flex justify-center bg-black text-white") {
props.getValue() :?> string
}
)
[<SolidComponent>]
let nameColumn = ColumnDef<User>(
accessorFn = fun user _ -> user.Name
,header = !!"Name"
,cell = fun props ->
div(class' = "w-14 hover:scale-102 flex justify-center bg-black text-white") {
props.getValue() :?> string
}
)
[<SolidComponent>]
let colorColumn = ColumnDef<User>(
accessorFn = fun user _ -> user.Color
,header = !!"Color"
,cell = fun props ->
div(class' = "w-14 hover:scale-102 flex justify-center bg-black text-white") {
props.getValue() :?> string
}
)
let columnDefs = [|
codeColumn
nameColumn
colorColumn
|]
let userData = [|
{ Name = "Name"; Color = "Color"; Code = "Code" }
{ Name = "Name1"; Color = "Color1"; Code = "Code1" }
{ Name = "Name2"; Color = "Color2"; Code = "Code2" }
|]
[<SolidComponent>]
let Test () =
let table = createTable(
TableOptions<User>(
getCoreRowModel = getCoreRowModel()
) .data(fun _ -> userData)
.columns(fun _ -> columnDefs)
)
DataTable(table = table)
import { twMerge } from "tailwind-merge";
import { clsx } from "clsx";
import { Show, For, splitProps } from "solid-js";
import { getCoreRowModel, createSolidTable, flexRender } from "@tanstack/solid-table";
import { Record } from "../fable_modules/fable-library-js.5.0.0-alpha.13/Types.js";
import { record_type, string_type } from "../fable_modules/fable-library-js.5.0.0-alpha.13/Reflection.js";
import "~/app.css";
export function Lib_cn_Z35CD86D0(classes) {
return twMerge(clsx(classes));
}
export function TableCaption(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <caption class={Lib_cn_Z35CD86D0(["mt-4 text-sm text-muted-foreground", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function Table(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <div class="relative w-full overflow-auto">
<table class={Lib_cn_Z35CD86D0(["w-full caption-bottom text-sm", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />
</div>;
}
export function TableHeader(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <thead class={Lib_cn_Z35CD86D0(["[&_tr]:border-b", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function TableBody(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <tbody class={Lib_cn_Z35CD86D0(["[&_tr:last-child]:border-0", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function TableFooter(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <tfoot class={Lib_cn_Z35CD86D0(["bg-primary font-medium text-primary-foreground", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function TableRow(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <tr class={Lib_cn_Z35CD86D0(["border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function TableHead(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <th class={Lib_cn_Z35CD86D0(["h-10 px-2 text-left align-middle font-medium\r\n text-muted-foreground [&:has([role=checkbox])]:pr-0", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function TableCell(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["class"]);
return <td class={Lib_cn_Z35CD86D0(["p-2 align-middle [&:has([role=checkbox])]:pr-0", PARTAS_LOCAL.class])}
{...PARTAS_OTHERS} bool:n$={false} />;
}
export function DataTable(props) {
const [PARTAS_LOCAL, PARTAS_OTHERS] = splitProps(props, ["table"]);
const table = PARTAS_LOCAL.table;
return <Table>
<TableHeader>
<For each={table.getHeaderGroups()}>
{(headerGroup, _arg) => <TableRow>
<For each={headerGroup.headers}>
{(header, _arg_1) => <TableHead colspan={header.colSpan}>
<Show when={!header.isPlaceholder}>
{flexRender(header.column.columnDef.header, header.getContext())}
</Show>
</TableHead>}
</For>
</TableRow>}
</For>
</TableHeader>
<TableBody>
<Show when={table.getRowModel().rows.length}
fallback={<TableRow>
<TableCell colspan={8}
class="h-24 text-center">
No Results.
</TableCell>
</TableRow>}>
<For each={table.getRowModel().rows}>
{(row, _arg_2) => <TableRow data-state={row.getIsSelected() && "selected"}>
<For each={row.getVisibleCells()}>
{(cell, _arg_3) => <TableCell>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>}
</For>
</TableRow>}
</For>
</Show>
</TableBody>
</Table>;
}
export class User extends Record {
constructor(Code, Name, Color) {
super();
this.Code = Code;
this.Name = Name;
this.Color = Color;
}
}
export function User_$reflection() {
return record_type("Partas.Solid.examples.datatable.User", [], User, () => [["Code", string_type], ["Name", string_type], ["Color", string_type]]);
}
export const codeColumn = {
accessorFn: (user, _arg) => user.Code,
header: "Code",
cell: (props) => <div class="w-14 hover:scale-102 flex justify-center bg-black text-white">
{props.getValue()}
</div>,
};
export const nameColumn = {
accessorFn: (user, _arg) => user.Name,
header: "Name",
cell: (props) => <div class="w-14 hover:scale-102 flex justify-center bg-black text-white">
{props.getValue()}
</div>,
};
export const colorColumn = {
accessorFn: (user, _arg) => user.Color,
header: "Color",
cell: (props) => <div class="w-14 hover:scale-102 flex justify-center bg-black text-white">
{props.getValue()}
</div>,
};
export const columnDefs = [codeColumn, nameColumn, colorColumn];
export const userData = [new User("Code", "Name", "Color"), new User("Code1", "Name1", "Color1"), new User("Code2", "Name2", "Color2")];
export function Test() {
let this$_3, this$_1;
const table = createSolidTable((this$_3 = ((this$_1 = {
getCoreRowModel: getCoreRowModel(),
}, (Object.defineProperty(this$_1, "data", {
get: () => userData,
}), this$_1))), (Object.defineProperty(this$_3, "columns", {
get: () => columnDefs,
}), this$_3)));
return <DataTable table={table} />;
}

Last updated: 7/10/25, 7:05 AM

PartasBuilt using the Partas.SolidStart SolidBase template
Community
githubdiscord