Bonfire.UI.Common.LiveHandlers (Bonfire v1.0.0-social-rc.1.13)

View Source

LiveHandlers provides a standardized way to handle various LiveView events (params, events, info) and route them to appropriate handler modules, enabling you to easily handle the same event in multiple live views or components using the same code.

Types of handlers

  • Events (eg. clicks or form submissions)
  • URL parameters
  • PubSub messages

Features

  • Routing events to specific LiveHandler modules based on naming conventions
  • Automatic error handling with ErrorHandling.undead/2
  • Built-in handlers for common operations (assign, redirect, etc.)
  • Support for direct function delegation

Usage Examples

Event Delegation

# In your template:
phx-submit="Bonfire.Posts:post"
# Will be routed to:
Bonfire.Posts.LiveHandler.handle_event("post", params, socket)

PubSub Handling

# When broadcasting:
PubSub.broadcast(feed_id, {{Bonfire.Social.Feeds, :new_activity}, activity})
# Will be routed to:
Bonfire.Social.Feeds.LiveHandler.handle_info({:new_activity, activity}, socket)

URL Parameter Handling

# For a URL like:
"?Bonfire.Social.Feeds[after]=cursor123"
# Will be routed to:
Bonfire.Social.Feeds.LiveHandler.handle_params(%{"after" => "cursor123"}, uri, socket)

Summary

Functions

Assigns socket values based on event attributes.

Handles LiveView events and delegates to appropriate LiveHandler modules.

Handles messages sent to the LiveView process and delegates to appropriate handlers.

Handles URL parameters and delegates to appropriate LiveHandler modules.

Handles upload progress events, delegating to a function or LiveHandler module.

Converts a JSON string to a map if it appears to be valid JSON.

Delegates a function call to a module's LiveHandler.

Functions

assign_attrs(socket, attrs)

Assigns socket values based on event attributes.

This function processes a map of attributes and assigns them to the socket, with options for converting to atoms and global assignment.

Parameters

  • socket: The Phoenix LiveView socket
  • attrs: Map of attributes to assign

Options (in attrs)

  • "to_atoms": Convert keys to atoms (true/false)
  • "to_integers": Convert values to integers (true/false)
  • "assign_global": Make global assigns (true/false)
  • "send_self": Send assigns to self (true/false)

Examples

# Simple assignment:
assign_attrs(socket, %{"name" => "User", "age" => "42"})

# With conversion options:
assign_attrs(socket, %{"name" => "User", "age" => "42", "to_atoms" => "true", "to_integers" => "true"})

Returns

Socket with assigned values

handle_event(action, attrs, socket, source_module \\ nil, fun \\ nil)

Handles LiveView events and delegates to appropriate LiveHandler modules.

This function processes events based on their name and delegates to the appropriate LiveHandler module.

Parameters

  • action: The event name or {module, action} tuple
  • attrs: The event parameters
  • socket: The Phoenix LiveView socket
  • source_module: (optional) The source module making the call
  • fun: (optional) Custom function to handle the event before delegation

Built-in Event Handlers

  • "assign" - Assigns values from the event parameters to the socket
  • "redirect" or "navigate" - Redirects to the specified path
  • "live_select_change" - Handles LiveSelect component events

Examples

# From a template:
phx-click="Bonfire.Posts:like"
# Delegates to:
Bonfire.Posts.LiveHandler.handle_event("like", params, socket)

Returns

{:noreply, socket}

handle_info(blob, socket, source_module \\ nil, fun \\ nil)

Handles messages sent to the LiveView process and delegates to appropriate handlers.

This function processes messages based on their structure and delegates to the appropriate LiveHandler module.

Parameters

  • blob: The message being handled
  • socket: The Phoenix LiveView socket
  • source_module: (optional) The source module making the call
  • fun: (optional) Custom function to handle the message before delegation

Built-in Message Handlers (handled directly with no delegation necessary)

  • :clear_flash - Clears all flash messages
  • {:assign, {key, value}} - Assigns a single key-value pair to the socket
  • {:assign, assigns} - Assigns multiple values to the socket
  • {:assign_global, assigns} - Assigns global values (using Surface's @__context__)
  • {:assign_persistent, assigns} - Sends assigns to PersistentLive
  • {:redirect, to} - Redirects to the specified path
  • {{module, name}, data} - Delegates to a LiveHandler

Examples

# Assign a value on the current LiveView
send(self(), {:assign, {key: :value}})

# Send a message to be handled by a specific LiveHandler
send(self(), {{Bonfire.Posts, :new_post}, post})
# Delegates to:
Bonfire.Posts.LiveHandler.handle_info({:new_post, post}, socket)

Returns

{:noreply, socket}

handle_params(params, uri, socket, source_module \\ nil, fun \\ nil)

Handles URL parameters and delegates to appropriate LiveHandler modules.

This function first checks if a specific handler function was provided, then attempts to delegate to a LiveHandler module based on URL query parameters.

Parameters

  • params: Map of URL query parameters
  • uri: Current URI string
  • socket: The Phoenix LiveView socket
  • source_module: (optional) The source module making the call
  • fun: (optional) Custom function to handle the params before attempting delegation

Examples

# When handling a URL like "?Bonfire.Users[filter]=active"
handle_params(%{"Bonfire.Users" => %{"filter" => "active"}}, "/users", socket)
# Delegates to:
Bonfire.Users.LiveHandler.handle_params(%{"filter" => "active"}, "/users", socket)

Returns

{:noreply, socket}

handle_progress(type, entry, socket, source_module, target_fn)

Handles upload progress events, delegating to a function or LiveHandler module.

This function handles upload progress events and delegates to either a function or a LiveHandler module.

Parameters

  • type: The type of upload (e.g., :avatar, :image)
  • entry: The upload entry containing progress information
  • socket: The Phoenix LiveView socket
  • source_module: The source module making the call
  • target_fn: Function to handle the progress event

Examples

# Delegating to a function:
handle_progress(:avatar, entry, socket, __MODULE__, &handle_avatar_upload/3)

# Define the handler function:
def handle_avatar_upload(type, entry, socket) do
  # Process avatar upload
  {:noreply, socket}
end
# Delegate to a module:
handle_progress(:avatar, entry, socket, __MODULE__, MyLiveHandler)

# Define the handler function in `MyLiveHandler`:
def handle_progress(type, entry, socket) do
  # Process avatar upload
  {:noreply, socket}
end

Returns

Result of the target function, typically {:noreply, socket}

maybe_from_json(json)

Converts a JSON string to a map if it appears to be valid JSON.

Parameters

  • json: String that might be JSON

Examples

iex> Bonfire.UI.Common.LiveHandlers.maybe_from_json("{"name":"test"}")
%{"name" => "test"}

iex> Bonfire.UI.Common.LiveHandlers.maybe_from_json("not json")
"not json"

Returns

Decoded JSON map or the original value

mod_delegate(mod, fun, args, socket, no_delegation_fn \\ &no_live_handler/2)

Delegates a function call to a module's LiveHandler.

This function attempts to find and call a function in a module's LiveHandler, with proper error handling and circular reference detection.

Parameters

  • mod: Module name (string or atom)
  • fun: Function name (atom)
  • args: Function arguments
  • socket: The Phoenix LiveView socket
  • no_delegation_fn: (optional) Function to call if delegation fails

Examples

# Delegate to a LiveHandler:
mod_delegate("Bonfire.Posts", :handle_event, ["like", %{id: 123}], socket)
# Calls:
Bonfire.Posts.LiveHandler.handle_event("like", %{id: 123}, socket)

Returns

Result of the delegated function call, for example {:noreply, socket}

sigil_p(route, extra)

(macro)