LineaUI.Components.DataTable (linea_ui v0.1.1)

Copy Markdown View Source

A table with a search box, sortable headers, a pagination footer and row selection, in the two looks LineOne shows: advanced (the Table Advanced page: a title bar with a search that slides open, the table as a card, "Show 10 entries" and a pager underneath) and grid (the Grid Table page: a search box on the right, sort arrows, "Showing 1 to 10 of 15 results" and Previous/Next).

The LiveView owns the state: it filters, sorts and slices the rows and gives the component the current page; the component only renders it and sends events back.

<.data_table
  id="users"
  rows={@users}
  search={@search}
  on_search="search"
  sort_by={@sort_by}
  sort_dir={@sort_dir}
  on_sort="sort"
  page={@page}
  page_size={10}
  total={@total}
  on_page="paginate"
>
  <:title>Users Table</:title>
  <:col :let={user} label="Name" sort_key="name">{user.name}</:col>
  <:col :let={user} label="Email">{user.email}</:col>
</.data_table>

def handle_event("search", %{"search" => q}, socket), do: ...
def handle_event("sort", %{"column" => col, "direction" => dir}, socket), do: ...
def handle_event("paginate", %{"page" => page}, socket), do: ...

Rows may be a stream (rows={@streams.users}); the body then renders with phx-update="stream" and total drives the footer. :col, :action, :expand, :empty, row_id, row_key, row_item, row_click and selection work as in LineaUI.Components.Table.table/1.

Summary

Functions

Renders a data table. The LiveView passes the rows of the current page and handles the events below.

The JS that opens and closes the filter panel of the data table with id (the :filters slot also receives it).

LineOne's collapsing search: a magnifier button that slides a borderless input open, as in the title bar of the Table Advanced page. data_table/1 uses it, and it works on its own next to any title.

Functions

data_table(assigns)

Renders a data table. The LiveView passes the rows of the current page and handles the events below.

<.data_table
  id="contacts"
  variant="grid"
  rows={@rows}
  total={@total}
  page={@page}
  on_page="paginate"
  search={@search}
  on_search="search"
  sort_by={@sort_by}
  sort_dir={@sort_dir}
  on_sort="sort"
  row_key={& &1.id}
  selected={@selected}
  on_select="select"
  on_select_all="select_all"
>
  <:col :let={c} label="Name" sort_key="name">{c.name}</:col>
  <:col :let={c} label="Email" sort_key="email">{c.email}</:col>
</.data_table>

Events, each an event name or a %JS{} (sent to target when given):

  • on_search — the search input changed or was submitted: %{"search" => query}.
  • on_sort — a sortable header was clicked: %{"column" => sort_key, "direction" => "asc" | "desc"}, the direction to sort by next.

  • on_page — a page was chosen: %{"page" => "3"} (a string, as every phx-value-*). With page_path (a function of the page number) the pager renders patch links instead.
  • on_page_size — the "Show N entries" select changed: %{"page_size" => "30"}.
  • on_select — a row checkbox: %{"id" => key, "selected" => "true" | "false"}.

  • on_select_all — the header checkbox: %{"selected" => "true" | "false"}.

The footer shows when on_page or page_path is given (unless footer={false}); the search when on_search is.

Attributes

  • id (:string) (required)
  • rows (:any) (required) - The rows of the current page, a list or a stream.
  • variant (:string) - Defaults to "advanced". Must be one of "advanced", or "grid".
  • row_id (:any) - A function giving each row's DOM id; streams default to the stream id. Defaults to nil.
  • row_key (:any) - A function giving a row's selection key; defaults to its DOM id. Defaults to nil.
  • row_item (:any) - Maps each row before the slots get it. Defaults to &Function.identity/1.
  • row_click (:any) - A function of the row returning a JS or an event name. Defaults to nil.
  • hoverable (:boolean) - Highlights the hovered row; on by default, off for expandable rows. Defaults to nil.
  • search (:string) - The current query. Defaults to "".
  • search_placeholder (:string) - Placeholder of the search input. Defaults to nil.
  • on_search (:any) - See the events above. Defaults to nil.
  • sort_by (:string) - The sort_key of the sorted column. Defaults to nil.
  • sort_dir (:string) - Direction of sort_by. Defaults to "asc". Must be one of "asc", or "desc".
  • on_sort (:any) - See the events above. Defaults to nil.
  • page (:integer) - The current page, from 1. Defaults to 1.
  • page_size (:integer) - Rows per page. Defaults to 10.
  • total (:integer) - Rows across every page. Defaults to the row count. Defaults to nil.
  • on_page (:any) - See the events above. Defaults to nil.
  • page_path (:any) - A function of the page number returning a path. Defaults to nil.
  • footer (:boolean) - false leaves out the footer (pager, summary and page-size select) even when on_page is given, for a table with only a search. Defaults to true.
  • compact (:boolean) - Tighter cells, see table/1. Defaults to false.
  • headless (:boolean) - No <thead>, see table/1. Defaults to false.
  • borderless (:boolean) - No row rules, see table/1. Defaults to false.
  • page_sizes (:list) - Options of the "Show N entries" select. Defaults to [].
  • on_page_size (:any) - See the events above. Defaults to nil.
  • pager (:string) - The pager look of the advanced variant. Defaults to "rounded". Must be one of "rounded", "pill", or "circle".
  • show_label (:string) - Text before the page-size select. Defaults to "Show".
  • entries_label (:string) - Text after the page-size select. Defaults to "entries".
  • prev_label (:string) - Text of the grid pager's first button. Defaults to "Previous".
  • next_label (:string) - Text of the grid pager's last button. Defaults to "Next".
  • selected (:list) - Keys of the selected rows. Defaults to [].
  • all_selected (:boolean) - Whether the header checkbox is checked; computed for lists. Defaults to nil.
  • on_select (:any) - See the events above. Defaults to nil.
  • on_select_all (:any) - See the events above. Defaults to nil.
  • expand_label (:string) - Header of the expand column. Defaults to nil.
  • target (:any) - phx-target of every event. Defaults to nil.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.

Slots

  • col (required) - A column; receives the row (after row_item). Accepts attributes:
    • label (:string) - Header text.
    • class (:any) - Extra classes of the column's cells (the header takes head_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" in on_sort.
  • title - The advanced variant's heading.
  • actions - Buttons at the right of the advanced title bar.
  • filters - A filter panel the advanced title bar's filter button opens. Receives the JS that toggles it.
  • summary - Replaces the "1 - 10 of 15 entries" text; receives %{first: n, last: n, total: n}.
  • action - Cells appended to every row.
  • expand - Detail under each row, see LineaUI.Components.Table.table/1.
  • empty - Shown when rows is an empty list.

data_table_toggle_filters(js \\ %JS{}, id)

@spec data_table_toggle_filters(Phoenix.LiveView.JS.t(), String.t()) ::
  Phoenix.LiveView.JS.t()

The JS that opens and closes the filter panel of the data table with id (the :filters slot also receives it).

<.button phx-click={data_table_toggle_filters("projects")}>Filters</.button>

table_search(assigns)

LineOne's collapsing search: a magnifier button that slides a borderless input open, as in the title bar of the Table Advanced page. data_table/1 uses it, and it works on its own next to any title.

<div class="flex items-center justify-between">
  <h2>Users</h2>
  <.table_search id="users" value={@search} on_search="search" />
</div>

Events: on_search (an event name or %JS{}, sent to target when given) receives %{"search" => query} on every change (debounced 300ms) and on submit. The input has the DOM id #{id}-search and the form #{id}-search-form. The input starts open when value is not empty.

Attributes

  • id (:string) (required)
  • value (:string) - The current query. Defaults to "".
  • on_search (:any) - Event name or %JS{} for the query changes. Defaults to nil.
  • target (:any) - phx-target of on_search. Defaults to nil.
  • placeholder (:string) - Placeholder and label; "Search here..." by default. Defaults to nil.
  • class (:any) - Defaults to nil.
  • Global attributes are accepted.