Current section

Files

Jump to
elixir_uikit usage-rules hooks.md
Raw

usage-rules/hooks.md

# LiveView Hooks
`elixir_uikit` exports three LiveView hooks: **Sortable**, **Modal**, and **Switcher**. These are automatically registered when you run `mix uikit.setup`.
## Sortable Hook
Enables drag-and-drop reordering with server-side sync.
### Setup
```heex
<.uk_sortable id="my-list" phx-hook="Sortable" data-event="reorder_items">
<div :for={item <- @items} id={"item-#{item.id}"} class="uk-card uk-card-default uk-card-body">
{item.name}
</div>
</.uk_sortable>
```
### Event
When items are reordered, the hook pushes an event to the server with the new order of element IDs.
- **Default event name:** `"uikit:reorder"`
- **Custom event name:** Set `data-event` on the container
- **Payload:** `%{"items" => ["item-3", "item-1", "item-2"]}`
### Server handler
```elixir
def handle_event("reorder_items", %{"items" => ids}, socket) do
# ids is a list of DOM element IDs in the new order
# Extract your record IDs and update positions
{:noreply, socket}
end
```
### Requirements
- The container **must** have an `id` and `phx-hook="Sortable"`.
- **Every child element must have a unique `id`** — otherwise LiveView cannot track reordered items.
---
## Modal Hook
Enables server-controlled modal show/hide via assigns.
### Setup
The hook is automatically attached when you use `show` on `uk_modal`:
```heex
<.uk_modal id="my-modal" show={@show_modal} on_close="modal_closed">
<:header><.uk_modal_title>Title</.uk_modal_title></:header>
<:body><p>Content</p></:body>
</.uk_modal>
```
### How it works
- Set `show={true}` to open the modal, `show={false}` to close it.
- When the user dismisses the modal (Esc key or background click), the hook pushes the `on_close` event (default: `"uikit:modal_closed"`) so you can sync state.
- **Payload:** `%{"id" => "my-modal"}`
### Server handler
```elixir
def handle_event("modal_closed", %{"id" => _id}, socket) do
{:noreply, assign(socket, show_modal: false)}
end
```
### Client-side only alternative
If you don't need server control, skip `show` and use `uk_toggle` on a button:
```heex
<.uk_button uk_toggle="target: #my-modal">Open</.uk_button>
<.uk_modal id="my-modal">
<:body>Content</:body>
</.uk_modal>
```
---
## Switcher Hook
Enables server-controlled tab switching via assigns.
### Setup
The hook is automatically attached when you use `active` on `uk_subnav`:
```heex
<.uk_subnav id="my-tabs" pill switcher="connect: #my-content" active={@active_tab} on_change="tab_changed">
<:item href="#">Tab 1</:item>
<:item href="#">Tab 2</:item>
<:item href="#">Tab 3</:item>
</.uk_subnav>
<.uk_switcher id="my-content">
<li>Content 1</li>
<li>Content 2</li>
<li>Content 3</li>
</.uk_switcher>
```
### How it works
- Set `active={0}`, `active={1}`, etc. to programmatically switch tabs.
- When the user clicks a tab, the hook pushes the `on_change` event (default: `"uikit:switcher_changed"`) with the new index.
- **Payload:** `%{"id" => "my-tabs", "index" => 1}`
### Server handler
```elixir
def handle_event("tab_changed", %{"index" => index}, socket) do
{:noreply, assign(socket, active_tab: index)}
end
```
### Client-side only alternative
If you don't need server-side tab state, omit `active` and `on_change`:
```heex
<.uk_subnav id="tabs" pill switcher="connect: #content">
<:item href="#">Tab 1</:item>
<:item href="#">Tab 2</:item>
</.uk_subnav>
<.uk_switcher id="content">
<li>Content 1</li>
<li>Content 2</li>
</.uk_switcher>
```