Mob.Event.Address (mob v0.6.10)

Copy Markdown View Source

Canonical address for an event in the Mob 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

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

Summary

Types

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.

t()

Functions

True if addr.render_id matches current_render_id.

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

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.

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

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

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

Types

id()

@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()

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

Functions

current?(address, current_render_id)

@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(opts)

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

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

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

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

same_widget?(a, b)

@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(a)

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

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

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

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

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

validate_id(id)

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

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

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

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

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

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

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

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

with_render_id(addr, render_id)

@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.