Search documentation of mob

# Mob.List (mob v0.6.18)

Copy Markdown View Source

Data-driven list component.

A `type: :list` node in your render tree is shorthand for a scrollable list backed by Elixir data. Mob expands it into a `lazy_list` before rendering, wrapping each row in a tappable container.

## Basic usage

The default renderer turns each item into a text row. No setup needed:

    %{
      type:  :list,
      props: %{id: :my_list, items: assigns.names},
      children: []
    }

Handle selections in `handle_info/2`:

    def handle_info({:select, :my_list, index}, socket) do
      item = Enum.at(socket.assigns.names, index)
      {:noreply, Mob.Socket.assign(socket, :selected, item)}
    end

## Custom renderer

Register a renderer in `mount/3` to control how each item looks:

    def mount(_params, _session, socket) do
      socket =
        socket
        |> Mob.Socket.assign(:items, load_items())
        |> Mob.List.put_renderer(:my_list, fn %{name: name, subtitle: sub} ->
          %{
            type: :column,
            props: %{padding: 12},
            children: [
              %{type: :text, props: %{text: name,  text_size: :base}, children: []},
              %{type: :text, props: %{text: sub,   text_size: :sm, text_color: :gray_500}, children: []}
            ]
          }
        end)
      {:ok, socket}
    end

## Default renderer rules

When no custom renderer is registered:

- Binary → text row with the string
- `%{label: _}` → text row with the label
- `%{text: _}` → text row with the text
- Anything else → `inspect/1` fallback

## Summary

### Functions

default_renderer(item)

The default item renderer. Handles binaries, maps with `:label`/`:text`, and falls back to `inspect/1` for anything else.

expand(node, renderers, pid)

Walk a render tree and expand all `type: :list` nodes into `lazy_list` nodes.

put_renderer(socket, id, renderer)

Register a custom item renderer for a list.

## Functions

# default_renderer(item)

    @spec default_renderer(term()) :: map()

The default item renderer. Handles binaries, maps with `:label`/`:text`, and falls back to `inspect/1` for anything else.

# expand(node, renderers, pid)

    @spec expand(map(), map(), pid()) :: map()

Walk a render tree and expand all `type: :list` nodes into `lazy_list` nodes.

Called internally by `Mob.Screen` before passing the tree to `Mob.Renderer`. `renderers` is the `list_renderers` map from `socket.__mob__`. `pid` is the screen process (used as the tap target for row-select events).

# put_renderer(socket, id, renderer)

    @spec put_renderer(Mob.Socket.t(), atom(), (term() -> map())) :: Mob.Socket.t()

Register a custom item renderer for a list.

`id` must match the `:id` prop on the `type: :list` node. `renderer` is a 1-arity function that receives one item and returns a node map.

Call this from `mount/3` or `handle_info/2` — it is stored in `socket.__mob__` and picked up at render time.