Which columns a table shows, and in what order, for each user — stored as
the "columns" field of the user's PhoenixKit.Users.ViewPrefs for the
table's key, edited through core's live column_settings_modal/1.
A table describes itself with a spec:
%{
key: "catalogue.detail_items", # the ViewPrefs key
columns: [%{id: "sku", label: fn -> gettext("SKU") end}, …],
defaults: ["sku", "price"], # optional; all columns when absent
site_default: &MyApp.site_columns/0, # optional; -> [id] | nil
min: 0 # optional; fewest a user may keep
}columns is exactly what the modal can show or hide. A column that is
always on (a Name, an Actions cell) is not in it: the table draws it
around the resolved list.
The rules
- A user who has not chosen sees the site's default when there is one
(
site_default), elsedefaults. Reset takes the user's choice back out, so they follow that default again — it does not save a copy of it. - An empty list is a choice: every optional column hidden — unless the
spec keeps a
:min: a choice or site default with fewer columns than that is not used, and the next default in line shows instead. - Ids no longer in
columns(a custom field deleted, an extension switched off) are skipped when reading and never rewritten by a read; when none of a non-empty choice is left, the default shows until the user changes something. - A change saves the list the user now sees — ids already skipped are not carried along.
In a LiveView
def handle_event(event, params, socket)
when event in ~w(add_column remove_column reorder_columns reset_columns) do
{:noreply, TableColumns.handle_event(event, params, socket, spec(), :columns)}
endhandle_event/5 updates the assign and saves for the signed-in user
(PhoenixKitWeb.Actor); with nobody signed in the change lasts for the
page. A LiveComponent has only the assigns its parent passed, so it needs
phoenix_kit_current_scope (or phoenix_kit_current_user) handed in, or
its choices are never saved.
A modal with several tables (sections) sends a "section" param with
add, remove and reorder — pick the spec by it and pass that. Reset carries
no section: it resets every table the modal shows, so handle it apart.
Summary
Functions
current with id added at the end — when it is offered and not shown yet.
What a user who has not chosen sees: the site's default, read by the
same rules as a user's choice (an empty one is a choice), else the
spec's defaults (all columns when there are none).
The events handle_event/5 answers.
Applies one of the modal's events (events/0) to the list in assign
name, saves it for the signed-in user, and answers the socket.
Anything else — an unknown event, a malformed param — leaves it alone.
The columns user sees for the table spec describes.
current without id — unless that would leave fewer than the spec's :min.
current in the order ordered gives. Ids ordered names that are not
shown are ignored; shown ones it leaves out keep their place at the end,
so a partial or crafted payload can reorder but never drop or add.
The columns a stored choice shows (see the rules in the moduledoc):
nil for no choice, else the stored list.
Types
Functions
current with id added at the end — when it is offered and not shown yet.
What a user who has not chosen sees: the site's default, read by the
same rules as a user's choice (an empty one is a choice), else the
spec's defaults (all columns when there are none).
@spec events() :: [String.t()]
The events handle_event/5 answers.
@spec handle_event(String.t(), map(), Phoenix.LiveView.Socket.t(), spec(), atom()) :: Phoenix.LiveView.Socket.t()
Applies one of the modal's events (events/0) to the list in assign
name, saves it for the signed-in user, and answers the socket.
Anything else — an unknown event, a malformed param — leaves it alone.
@spec load(PhoenixKit.Users.ViewPrefs.user(), spec()) :: [String.t()]
The columns user sees for the table spec describes.
current without id — unless that would leave fewer than the spec's :min.
current in the order ordered gives. Ids ordered names that are not
shown are ignored; shown ones it leaves out keep their place at the end,
so a partial or crafted payload can reorder but never drop or add.
The columns a stored choice shows (see the rules in the moduledoc):
nil for no choice, else the stored list.