How to Create Nested LiveView Components
From ElixirBlocks
This example demonstrates a nested LiveView component.
defmodule AppxWeb.SandboxLive do
use AppxWeb, :live_view
import MyComponent
def mount(_params, _session, socket) do
{:ok, socket}
end
def render(assigns) do
~H"""
Hello World! YAY
<MyComponent.greet name="Jane" />
"""
end
end
defmodule MyComponent do use Phoenix.Component def greet(assigns) do ~H""" <p>Hello, <%= @name %>!</p> """ end end
An Example of a Button
# 1. Create component with phx-click attributes for event handlers and a render slot fo text: <%= render_slot(@inner_block) %>
defmodule Example do
use Phoenix.Component
def simple_button(assigns) do
~H"""
<button
style="background-color: #000000; color: #ffffff; padding: 8px 16px; border-radius: 4px; font-weight: bold;"
phx-click={@on_click}
>
<%= render_slot(@inner_block) %>
</button>
"""
end
end
#___________PARENT
defmodule AppWeb.PageLive do
use AppWeb, :live_view
import Example
def mount(_params, _session, socket) do
# Initialize state with a counter
socket = assign(socket, count: 0)
{:ok, socket}
end
def render(assigns) do
~H"""
<div class="container mx-auto p-4">
<h1 class="text-xl font-bold mb-4">Counter with Button Component</h1>
<div class="mb-4">
<p>Current count: <span class="font-bold"><%= @count %></span></p>
</div>
<!-- # 2 add component to parent. Event handlers will come from parent-->
<Example.simple_button on_click="increment">
<span>Click to increment</span>
</Example.simple_button>
</div>
"""
end
# Event handler in the parent LiveView
def handle_event("increment", _params, socket) do
{:noreply, assign(socket, count: socket.assigns.count + 1)}
end
end