Handle events in your Live Views with LiveHandlers
View SourceBonfire.UI.Common.LiveHandlers
is a core module that simplifies event delegation for Phoenix LiveView applications within the Bonfire ecosystem. It 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.
Overview
The LiveHandlers system allows you to:
- Define event handling logic in dedicated modules
- Route events from multiple views or components based on naming conventions
- Handle complex event delegation scenarios
- Standardize error handling across your application
Usage
Creating a LiveHandler module
To create a LiveHandler for your Bonfire extension:
defmodule Bonfire.MyExtension.LiveHandler do
use Bonfire.UI.Common.Web, :live_handler
# Implement handler callbacks
def handle_event("my_action", params, socket) do
# Your handling logic
{:noreply, socket}
end
def handle_info({:my_message, data}, socket) do
# Process the message
{:noreply, socket}
end
def handle_params(%{"my_param" => value}, uri, socket) do
# Handle URL parameters
{:noreply, socket}
end
end
Triggering LiveHandlers
From Templates
You can trigger the handle_event
in your LiveHandler from any view or component:
<button phx-click="Bonfire.MyExtension:perform_action">Click me</button>
<form phx-submit="Bonfire.MyExtension:save_form">
<!-- form content -->
</form>
From URIs
You can trigger handle_params
in your LiveHandler based on on URIs:
<a href="?Bonfire.MyExtension[after]=<%= e(@page_info, :end_cursor, nil) %>">Load more</a>
From PubSub
You can trigger handle_info
in your LiveHandler from any live view or component:
PubSub.broadcast(topic, {{Bonfire.MyExtension, :new_item}, item})
Examples
Handle Form Submission
In your view or component:
<form phx-submit="Bonfire.MyExtension:save_form">
<!-- form content -->
</form>
In your LiveHandler module:
def handle_event("save_form", %{"post" => post_attrs}, socket) do
case Posts.create(current_user(socket), post_attrs) do
{:ok, post} ->
{:noreply, socket |> assign_flash(:info, "Post created successfully!")}
{:error, changeset} ->
{:noreply, socket |> assign(:changeset, changeset) |> assign_error("Failed to create post")}
end
end
Handle URL Parameters
In your view or component:
<a href="?Bonfire.MyExtension[after]=<%= e(@page_info, :end_cursor, nil) %>">
Load more
</a>
def handle_params(%{"after" => cursor}, _uri, socket) do
items = fetch_items_after_cursor(cursor)
{:noreply, socket |> assign(:items, items)}
end
Key Concepts
Event Routing
LiveHandlers uses naming conventions to route events:
phx-click="Bonfire.Posts:delete"
andphx-submit="Bonfire.Posts.LiveHandler:delete"
both route toBonfire.Posts.LiveHandler.handle_event("delete", ...)
PubSub.broadcast(topic, {{Bonfire.Social.Feeds, :new_activity}, activity})
andPubSub.broadcast(topic, {"Bonfire.Social.Feeds.LiveHandler:new_activity", item})
both route toBonfire.Social.Feeds.LiveHandler.handle_info({:new_activity, activity}, ...)
?Bonfire.Social.Feeds[after]=<cursor>
and/?Bonfire.Social.Feeds[after]=<cursor>
and/any_view?Bonfire.Social.Feeds.LiveHandler[after]=<cursor>
all route toBonfire.Social.Feeds.LiveHandler.handle_params(%{"after" => cursor}, ...)
Error Handling
All LiveHandler callbacks are wrapped in error protection using ErrorHandling.undead/2
to prevent crashes.
API Documentation
For more detailed documentation, see the Bonfire.UI.Common.LiveHandlers
module documentation.