# `Dala.Event.Address`
[🔗](https://github.com/manhvu/dala/blob/main/lib/dala/event/address.ex#L1)

Canonical address for an event in the Dala view tree.

An address identifies *where* a widget lives (`screen` and `component_path`)
and *what* fired (`widget`, `id`, `instance`). It also carries `render_id`
so handlers can detect events from prior render generations.

See `guides/event_model.md` for the full event model.

## Example

    %Dala.Event.Address{
      screen:         MyApp.CheckoutScreen,
      component_path: [:checkout_form],
      widget:         :button,
      id:             :submit,
      instance:       nil,
      render_id:      42
    }

# `id`

```elixir
@type id() :: atom() | binary() | integer() | float() | tuple() | map() | list()
```

Anything pattern-matchable that survives serialisation. Atoms are best for
compile-time-known IDs; binaries for data-derived ones (DB IDs, UUIDs);
integers/tuples for indices and compound keys.

Floats, maps, and lists are technically allowed but discouraged: floats have
fuzzy equality, maps and lists are heavy to hash on every event.

Pids, refs, and funs are explicitly forbidden — they don't survive
serialisation and can't be the basis of a stable address across re-renders.

# `t`

```elixir
@type t() :: %Dala.Event.Address{
  component_path: [id()],
  id: id(),
  instance: id() | nil,
  render_id: pos_integer(),
  screen: atom() | pid(),
  widget: atom()
}
```

# `current?`

```elixir
@spec current?(t(), pos_integer()) :: boolean()
```

True if `addr.render_id` matches `current_render_id`.

Use to detect stale events arriving after a re-render.

# `new`

```elixir
@spec new(keyword()) :: t()
```

Build an address. `screen`, `widget`, and `id` are required. The rest take
reasonable defaults.

    iex> Dala.Event.Address.new(screen: MyScreen, widget: :button, id: :save)
    %Dala.Event.Address{screen: MyScreen, widget: :button, id: :save, component_path: [], instance: nil, render_id: 1}

    iex> Dala.Event.Address.new(screen: MyScreen, widget: :list, id: :contacts, instance: 47, render_id: 12)
    %Dala.Event.Address{screen: MyScreen, widget: :list, id: :contacts, instance: 47, component_path: [], render_id: 12}

# `same_widget?`

```elixir
@spec same_widget?(t(), t()) :: boolean()
```

True if the address points to the same logical widget as `other`. Ignores
`render_id` — useful for "is this another tap on the same button?" checks.

# `to_string`

```elixir
@spec to_string(t()) :: binary()
```

Format an address as a short, human-readable string for logs.

    iex> Dala.Event.Address.to_string(%Dala.Event.Address{screen: MyScreen, widget: :button, id: :save})
    "MyScreen→button#save"

    iex> Dala.Event.Address.to_string(%Dala.Event.Address{screen: MyScreen, component_path: [:form], widget: :text_field, id: :email})
    "MyScreen/form→text_field#email"

    iex> Dala.Event.Address.to_string(%Dala.Event.Address{screen: MyScreen, widget: :list, id: :contacts, instance: 47})
    "MyScreen→list#contacts[47]"

# `validate_id`

```elixir
@spec validate_id(term()) :: :ok | {:error, atom()}
```

Validate that `id` is one of the supported types. Returns `:ok` or
`{:error, reason}`.

Used by `Dala.Ui.Renderer` and `Dala.Event` to fail fast when an obviously-bad
ID is passed (e.g. a pid, a function, or an undefined value).

    iex> Dala.Event.Address.validate_id(:save)
    :ok

    iex> Dala.Event.Address.validate_id("contact:42")
    :ok

    iex> Dala.Event.Address.validate_id(42)
    :ok

    iex> Dala.Event.Address.validate_id(self())
    {:error, :pid_not_allowed}

    iex> Dala.Event.Address.validate_id(nil)
    {:error, :nil_not_allowed}

# `with_render_id`

```elixir
@spec with_render_id(t(), pos_integer()) :: t()
```

Bump the render id on an address (e.g. when re-registering a widget after a
render). Returns a new address; original is unchanged.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
