<.sortable_list>: drag-and-drop lists (SortableJS), through Xenia's official adapter.
Setup
Install the library in your app:
npm install sortablejs --prefix assetsPass it to the adapter, and register it, in assets/js/app.js:
import { createSortablejs } from "xenia/sortablejs"
const sortablejs = createSortablejs({
load: () => import("sortablejs"),
})
hooks: { ...colocatedHooks, ...createHooks({ SortableJS: sortablejs }) },Then import Xenia.Adapters.SortableJS in html_helpers, and render
<.sortable_list id="..."> with the props below. Every event becomes an
on_<event> attribute; commands go through Xenia.push_to/4.
The factory returns a plain adapter object: spread it to add or change props, commands and events, without copying the adapter.
The tag uses the adapter name "SortableJS". To register it under
another name, render <.xenia adapter="..."> or declare your own tag.
Reference
Xenia's official adapter for SortableJS: a drag-and-drop list, optionally sharing items with other lists (kanban boards) and working as a form field.
Inside Xenia's container the server can't render children, so the
adapter renders the items itself from the items prop. Labels are set as
text, never as HTML.
Props:
items [%{id, label, disabled?, class?}] the list, in order
group a group name: lists with the same name exchange items. Or
%{name, pull: true | false | "clone", put: true | false}
handle true shows a drag handle; only the handle starts a drag
disabled true turns dragging off
list_class, item_class extra CSS classes for the <ul> and each <li>
options any other SortableJS option, snake_case or camelCase:
animation, ghost_class, delay, swap_threshold, sort, ...Commands:
reset re-render from the last `items` prop, e.g. after
the server refused a move without changing `items`Events:
sort %{ids, item_id, old_index, new_index} reordered within this list
add %{ids, item_id, new_index, from} received from another list
remove %{ids, item_id, old_index, to} moved to another list
error %{source, message, code}
`ids` is this list's order after the change; `from`/`to` are the other
list's component id. A move between lists sends `remove` from one and
`add` from the other: update both lists' items on the server.Form field: with field={@form[:order]}, the ids are submitted as a JSON array string, e.g. "["a","c","b"]" (decode it with Jason).
Summary
Functions
Attributes
id(:string) (required) - Stable DOM id used for adapter commands.items(:list) (required)group(:any)handle(:boolean)disabled(:boolean)list_class(:string)item_class(:string)options(:map)on_sort(:string) - LiveView event triggered when the adapter emits :sort. Defaults tonil.on_add(:string) - LiveView event triggered when the adapter emits :add. Defaults tonil.on_remove(:string) - LiveView event triggered when the adapter emits :remove. Defaults tonil.on_error(:string) - LiveView event triggered when the adapter emits :error. Defaults tonil.shortcuts(:map) - Key combination => LiveView event, while focus is inside (see Xenia.Shortcuts). Defaults to%{}.on_crash(:string) - LiveView event sent if the adapter throws (see Xenia.Component). Defaults tonil.- Global attributes are accepted.
Slots
loading- Shown until the island's first mount finishes.error- Shown if the adapter throws; data-xenia-retry starts it again.