Server-rendered components
A Dstar.Component owns the stage UI and its event handlers. This page embeds it on first render; events dispatch straight to the component.
Demo
Variants
Component stage
renders: 0
Ada Lovelace
Release coordinator · Dstar lab
- Open commands
- 7
- Patch latency
- 34 ms
- Signal scope
- tab
How it works
- ComponentStage is a Dstar.Component: UI plus handle_event/3.
- This page has no handle_event clauses for the stage at all.
- event/2 targets /ds/<module>/<event> via dstar_components/2.
- The same component renders on first paint and in SSE patches.
ComponentStage
is a Dstar.Component: it owns both its markup and
its handle_event/3. Events target /ds/<module>/<event>, so this page
module has no handler clauses for the stage at all — and the same component function
renders on first paint and inside every later patch.
<.action_button
id="component-profile"
label="Profile"
icon="hero-identification-micro"
click={"$component_kind = 'profile'; #{ComponentStage.event("profile")}"}
active={@component_kind == "profile"}
data-class={variant_classes("profile")}
/>
If this were LiveView
Both sides colocate the stage's markup with the handler that updates it, and both re-render the same function on first paint and on every update.
Dstar
<.action_button
id="component-profile"
label="Profile"
icon="hero-identification-micro"
click={"$component_kind = 'profile'; #{ComponentStage.event("profile")}"}
active={@component_kind == "profile"}
data-class={variant_classes("profile")}
/>
LiveView
# Illustrative LiveView equivalent — not compiled or run.
defmodule DstarDemoWeb.ComponentStageLive do
use DstarDemoWeb, :live_component
def render(assigns) do
~H"""
<div id={@id}>
<button phx-click="profile" phx-target={@myself}>Profile</button>
<button phx-click="timeline" phx-target={@myself}>Timeline</button>
<button phx-click="deploy" phx-target={@myself}>Deploy</button>
<p>{@component_kind} · renders: {@render_count}</p>
</div>
"""
end
def handle_event(kind, _params, socket) do
{:noreply,
assign(socket,
component_kind: kind,
render_count: socket.assigns.render_count + 1
)}
end
end
# In the parent LiveView:
#
# <.live_component
# module={DstarDemoWeb.ComponentStageLive}
# id="component-stage"
# component_kind={@component_kind}
# render_count={@render_count}
# />