LineOne's tables: basic, bordered, hoverable, zebra and the grid look, with :col slots
the way Phoenix's generated CoreComponents.table/1 takes them.
<.table id="users" rows={@users}>
<:col :let={user} label="Name">{user.name}</:col>
<:col :let={user} label="Job">{user.job}</:col>
</.table>
<.table id="users" rows={@streams.users} variant="hoverable" row_click={&JS.navigate(~p"/users/#{elem(&1, 1)}")}>
<:col :let={{_id, user}} label="Name">{user.name}</:col>
<:action :let={{_id, user}}><.button size="xs">Edit</.button></:action>
</.table>variant="hoverable" and "zebra" draw the filled header; rounded picks its corners:
row rounds both ends of the header row (a table inside a padded card), top only the
top corners (a table that is the top of a card) and none keeps it square (full width).
Sortable headers: give a column sort_key and the table on_sort; the header becomes a
button that sends on_sort with %{"column" => sort_key, "direction" => "asc" | "desc"},
the direction being the one to sort by next. sort_by and sort_dir mark the current order.
<.table id="t" rows={@rows} on_sort="sort" sort_by={@sort_by} sort_dir={@sort_dir}>
<:col :let={row} label="Name" sort_key="name">{row.name}</:col>
</.table>Row selection: on_select adds a checkbox column. Each checkbox sends on_select with
%{"id" => key, "selected" => "true" | "false"} (the new state of that row); the header one
sends on_select_all with %{"selected" => "true" | "false"}. selected is the list of keys
checked. The key is row_key.(row), or the row's DOM id when row_key is not given; keys
are compared as given, so pass strings or convert the "id" back.
Density and chrome: compact tightens the cell padding, borderless drops the row rules (and
the cell borders of bordered), headless leaves out the <thead> altogether. A column's
align (left, center, right) aligns its header and cells.
<.table id="stats" rows={@rows} compact borderless headless>
<:col :let={row}>{row.label}</:col>
<:col :let={row} align="right">{row.count}</:col>
</.table>Every event attr takes an event name or a %JS{}; target sets phx-target.
Expandable rows: an :expand slot adds a last column with a chevron that shows a detail
row under each row (expand_label names that column). The slot receives
%{row: row, toggle: js}, toggle being the JS that opens and closes it. Expandable
rows render one <tbody> per row, so they take a list, not a stream.
Summary
Functions
Renders a table of rows (a list or a stream), one column per :col slot.
The JS that shows or hides the detail panel of the expandable row with DOM id row_id
(the toggle the :expand slot receives is this, already bound to its row).
Functions
Renders a table of rows (a list or a stream), one column per :col slot.
<.table id="people" rows={@streams.people} variant="zebra">
<:col :let={{_id, person}} label="Name">{person.name}</:col>
<:col :let={{_id, person}} label="Job">{person.job}</:col>
<:action :let={{_id, person}}>
<.button size="xs" phx-click="edit" phx-value-id={person.id}>Edit</.button>
</:action>
</.table>Events (each an event name or a %JS{}, sent to target when given):
on_sort— a sortable header was clicked:%{"column" => sort_key, "direction" => "asc" | "desc"}(the direction to sort by next).on_select— a row checkbox:%{"id" => key, "selected" => "true" | "false"}.on_select_all— the header checkbox:%{"selected" => "true" | "false"}.
With a stream, selected only reaches the rows the server re-renders: stream_insert the
rows whose selection changed, and give all_selected for the header checkbox.
Attributes
id(:string) (required)rows(:any) (required) - A list or a@streams.xstream.row_id(:any) - A function giving each row's DOM id. Streams default to the stream id. Defaults tonil.row_click(:any) - A function of the row returning aJSor an event. Defaults tonil.row_item(:any) - Maps each row before it is given to the slots. Defaults to&Function.identity/1.row_key(:any) - A function giving the selection key of a row. Defaults to the row's DOM id. Defaults tonil.variant(:string) -gridis the gridjs look of LineOne's Grid Table page. Defaults to"basic". Must be one of"basic","bordered","hoverable","zebra", or"grid".rounded(:string) - Corners of the filled header ofhoverableandzebra. Defaults to"row". Must be one of"row","top", or"none".sort_by(:string) - Thesort_keyof the sorted column. Defaults tonil.sort_dir(:string) - Direction ofsort_by. Defaults to"asc". Must be one of"asc", or"desc".on_sort(:any) - Event sent when a sortable header is clicked. Defaults tonil.on_select(:any) - Event sent when a row checkbox is clicked. Defaults tonil.on_select_all(:any) - Event sent by the header checkbox. Defaults tonil.selected(:list) - The keys of the selected rows. Defaults to[].all_selected(:boolean) - Whether the header checkbox is checked. Computed for lists; give it for streams. Defaults tonil.hoverable(:boolean) - Highlights the hovered row. Defaults to the variant's own behavior. Defaults tonil.compact(:boolean) - Tighter cells:px-3 py-2instead of the variant's padding. Defaults tofalse.headless(:boolean) - Renders no<thead>at all (not hidden columns), for list-like tables. Defaults tofalse.borderless(:boolean) - Removes the rules between rows, and the cell borders of theborderedvariant. Defaults tofalse.target(:any) -phx-targetof the events. Defaults tonil.expand_label(:string) - Header of the expand column. Defaults tonil.wrapper_class(:any) - Classes of the scrolling wrapper. Defaults tonil.class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
col(required) - A column; receives the row (afterrow_item). Accepts attributes:label(:string) - Header text.class(:any) - Extra classes of the column's cells (the header takeshead_class).head_class(:any) - Extra classes of the column's header.align(:string) - Text alignment of the column's header and cells. Must be one of"left","center", or"right".sort_key(:string) - Makes the header sortable; sent as"column"inon_sort.
action- Cells appended to every row, after the columns.expand- Detail shown under a row; receives%{row: row, toggle: js}.empty- Shown in a full-width row whenrowsis an empty list.
@spec table_toggle_row(Phoenix.LiveView.JS.t(), String.t()) :: Phoenix.LiveView.JS.t()
The JS that shows or hides the detail panel of the expandable row with DOM id row_id
(the toggle the :expand slot receives is this, already bound to its row).
<.button phx-click={table_toggle_row("devs-row-0")}>Details</.button>