Last active
September 10, 2025 05:33
-
-
Save ukutaht/c296df0b1516d82372cd4f2d83b6a67e to your computer and use it in GitHub Desktop.
Liveview dynamic rendering issue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env elixir | |
# Minimal Phoenix LiveView single file example | |
# Run with: elixir minimal_liveview.exs | |
# Access at: http://localhost:4001 | |
Application.put_env(:minimal_app, MinimalApp.Endpoint, | |
http: [ip: {127, 0, 0, 1}, port: 4001], | |
server: true, | |
live_view: [signing_salt: "aaaaaaaa"], | |
secret_key_base: String.duplicate("a", 64), | |
debug_errors: true | |
) | |
Mix.install([ | |
{:plug_cowboy, "~> 2.5"}, | |
{:jason, "~> 1.0"}, | |
{:phoenix, "~> 1.7"}, | |
{:phoenix_live_view, "~> 1.0"} | |
]) | |
defmodule MinimalApp.ErrorHTML do | |
def render(template, _assigns) do | |
Phoenix.Controller.status_message_from_template(template) | |
end | |
end | |
defmodule MinimalApp.Layouts do | |
use Phoenix.Component | |
def app(assigns) do | |
~H""" | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1" /> | |
<meta name="csrf-token" content={Plug.CSRFProtection.get_csrf_token()} /> | |
<title>Minimal LiveView</title> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/priv/static/phoenix.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/priv/static/phoenix_live_view.min.js"></script> | |
<style> | |
body { font-family: system-ui, sans-serif; margin: 40px; } | |
.container { max-width: 800px; } | |
button { padding: 8px 16px; margin: 4px; background: #3b82f6; color: white; border: none; border-radius: 4px; cursor: pointer; } | |
button:hover { background: #2563eb; } | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<%= @inner_content %> | |
</div> | |
<script> | |
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") | |
let liveSocket = new window.LiveView.LiveSocket("/live", window.Phoenix.Socket, {params: {_csrf_token: csrfToken}}) | |
liveSocket.connect() | |
</script> | |
</body> | |
</html> | |
""" | |
end | |
end | |
defmodule MinimalApp.Components do | |
use Phoenix.Component | |
attr :type, :string, default: nil | |
attr :class, :string, default: nil | |
attr :rest, :global, include: ~w(disabled form name value) | |
slot :inner_block, required: true | |
def button(assigns) do | |
~H""" | |
<button | |
type={@type} | |
class={@class} | |
{@rest} | |
> | |
{render_slot(@inner_block)} | |
</button> | |
""" | |
end | |
attr :class, :string, default: "" | |
attr :as, :any, default: nil | |
slot :inner_block, required: true | |
def dropdown_trigger(assigns) do | |
assigns[:as].(assigns) | |
end | |
end | |
defmodule MinimalApp.HomeLive do | |
use Phoenix.LiveView | |
def mount(_params, _session, socket) do | |
{:ok, socket} | |
end | |
def render(assigns) do | |
~H""" | |
<MinimalApp.Components.dropdown_trigger as={&MinimalApp.Components.button/1} /> | |
""" | |
end | |
end | |
defmodule MinimalApp.Router do | |
use Phoenix.Router | |
import Phoenix.Controller | |
import Phoenix.LiveView.Router | |
pipeline :browser do | |
plug :accepts, ["html"] | |
plug :fetch_session | |
plug :fetch_live_flash | |
plug :put_root_layout, html: {MinimalApp.Layouts, :app} | |
plug :protect_from_forgery | |
end | |
scope "/", MinimalApp do | |
pipe_through :browser | |
live "/", HomeLive | |
end | |
end | |
defmodule MinimalApp.Endpoint do | |
use Phoenix.Endpoint, otp_app: :minimal_app | |
@session_options [ | |
store: :cookie, | |
key: "_minimal_app_key", | |
signing_salt: "aaaaaaaa" | |
] | |
socket "/live", Phoenix.LiveView.Socket, | |
websocket: [connect_info: [session: @session_options]] | |
plug Plug.RequestId | |
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] | |
plug Plug.Parsers, | |
parsers: [:urlencoded, :multipart, :json], | |
pass: ["*/*"], | |
json_decoder: Phoenix.json_library() | |
plug Plug.MethodOverride | |
plug Plug.Head | |
plug Plug.Session, @session_options | |
plug MinimalApp.Router | |
end | |
# Start the application | |
{:ok, _} = Supervisor.start_link([MinimalApp.Endpoint], strategy: :one_for_one) | |
IO.puts("\n๐ Minimal Phoenix LiveView started!") | |
IO.puts("๐ฑ Open http://localhost:4001 in your browser") | |
IO.puts("๐ Press Ctrl+C to stop\n") | |
Process.sleep(:infinity) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment