Corex. DataTable. Sort
(Corex v0.1.2)
View Source
Helpers for sortable data_table/1 usage in LiveViews.
Use with Corex.DataTable: set sort_by, sort_order, on_sort, and
a name on each sortable column (see the Sortable pattern in
data_table/1 docs). In the LiveView, call
assign_for_sort/3 in mount/3, then handle_sort/3 from the on_sort event handler.
Set :sort_columns in assign_for_sort/3 to whitelist sortable columns on the server. When
omitted, :sort_columns is inferred from atom keys on the first row map. Prefer an explicit
list when rows carry extra keys not shown in the table.
Example (in-memory rows)
def mount(_params, _session, socket) do
socket =
socket
|> assign(:users, fetch_users())
|> Corex.DataTable.Sort.assign_for_sort(:users,
default_sort_by: :id,
default_sort_order: :asc,
sort_columns: [:id, :name]
)
{:ok, socket}
end
def handle_event("sort", params, socket) do
{:noreply, Corex.DataTable.Sort.handle_sort(socket, params, :users)}
end
def render(assigns) do
~H"""
<.data_table
id="users-table"
rows={@users}
sort_by={@sort_by}
sort_order={@sort_order}
on_sort="sort"
>
<:col :let={user} label="ID" name={:id}>{user.id}</:col>
<:col :let={user} label="Name" name={:name}>{user.name}</:col>
</.data_table>
"""
endExample (database-backed rows)
def mount(_params, _session, socket) do
{rows, total} = MyApp.list_cities(page: 1, page_size: 10, order_by: :name, order_dir: :asc)
{:ok,
socket
|> assign(:cities, rows)
|> assign(:sort_columns, [:name])
|> assign(:sort_by, :name)
|> assign(:sort_order, :asc)
|> assign(:total, total)}
end
def handle_event("sort", %{"sort_by" => sort_by_param}, socket) do
case Corex.DataTable.Sort.parse_sort_by(sort_by_param, socket.assigns.sort_columns) do
{:ok, sort_by} ->
order =
if socket.assigns.sort_by == sort_by do
if socket.assigns.sort_order == :asc, do: :desc, else: :asc
else
:asc
end
{rows, total} =
MyApp.list_cities(
page: 1,
page_size: socket.assigns.page_size,
order_by: sort_by,
order_dir: order
)
{:noreply,
socket
|> assign(:cities, rows)
|> assign(:sort_by, sort_by)
|> assign(:sort_order, order)
|> assign(:total, total)}
:error ->
{:noreply, socket}
end
end
Summary
Functions
Assigns sort state and sorts the rows for a data_table/1 instance.
Handles the on_sort event from data_table/1 and returns the updated socket.
Parses a "sort_by" param from a LiveView event against an optional column whitelist.
Functions
Assigns sort state and sorts the rows for a data_table/1 instance.
Use in mount/3 after assigning the list. Options:
:default_sort_by– atom; columnnameondata_table/1(e.g.:id):default_sort_order–:ascor:desc, default:asc:sort_columns– list of atoms the browser may sort by (e.g.[:id, :name]). When omitted, inferred from atom keys on the first row inrows_assign. Prefer an explicit list in production when row maps include keys you do not expose as sortable columns.
The socket must already have an assign at rows_assign (e.g. :users) with the same list
passed as rows to data_table/1. Adds :sort_by,
:sort_order, :sort_columns, and replaces the rows assign with the sorted list.
Handles the on_sort event from data_table/1 and returns the updated socket.
Use in handle_event("sort", params, socket) (same name as on_sort) and return
{:noreply, Corex.DataTable.Sort.handle_sort(socket, params, :users)}.
params must contain "sort_by" (string, e.g. "id"). Only columns in :sort_columns from
assign_for_sort/3 are accepted. Unknown or disallowed values never crash
the LiveView process.
rows_assign is the assign key passed to data_table/1 as rows.
Parses a "sort_by" param from a LiveView event against an optional column whitelist.
Returns {:ok, atom} when the param is a safe existing atom and is allowed, or :error otherwise.
When sort_columns is nil, always returns :error. Use in database-backed handlers before
calling your context with order_by.