100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Elixir and LiveView

How Phoenix LiveView delivers real-time, interactive UIs from server-rendered Elixir without hand-written JavaScript.

Practical ElixirIntermediate10 min readJul 10, 2026
Analogies

What Is Phoenix LiveView?

Phoenix LiveView lets you build rich, real-time user interfaces in server-rendered Elixir, without writing client-side JavaScript frameworks like React or Vue. After an initial HTTP render, LiveView upgrades the connection to a persistent WebSocket; from then on, only minimal, diffed HTML patches are sent to the browser whenever server-side state changes, and Phoenix's own JavaScript client (phoenix_live_view.js) applies those patches to the DOM.

🏏

Cricket analogy: LiveView is like a stadium's giant screen that updates live with every ball, giving fans a real-time experience without them needing to refresh anything themselves.

The LiveView Lifecycle: mount, render, and handle_event

A LiveView module implements mount/3, which sets up initial socket.assigns (the view's state) and is called once for the initial HTTP request and again when the WebSocket connects. render/1 (or a colocated .html.heex template) declares the HTML based on current assigns using HEEx syntax with <%= @count %> interpolation. handle_event/3 responds to client-triggered events (like phx-click="increment"), typically updating assigns with assign/3 or update/3, which triggers a re-render and a diffed patch sent over the socket.

🏏

Cricket analogy: The mount/3 callback is like the toss at the start of a match — it sets up the initial state (who's batting) before any deliveries are bowled.

elixir
defmodule MyAppWeb.CounterLive do
  use MyAppWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, count: 0)}
  end

  def render(assigns) do
    ~H"""
    <div>
      <p>Count: <%= @count %></p>
      <button phx-click="increment">+1</button>
    </div>
    """
  end

  def handle_event("increment", _params, socket) do
    {:noreply, update(socket, :count, &(&1 + 1))}
  end
end

Real-Time Updates with PubSub

For updates that originate outside a single user's interaction — like a new comment posted by another user — LiveView processes subscribe to topics via Phoenix.PubSub.subscribe/2 in mount/3, and any process can broadcast a message with Phoenix.PubSub.broadcast/3. The subscribed LiveView's handle_info/2 callback receives the broadcast message, updates its assigns accordingly, and Phoenix automatically re-renders and pushes the diff to that specific connected client — enabling multi-user real-time features without any custom WebSocket plumbing.

🏏

Cricket analogy: Phoenix PubSub broadcasting a score update is like the stadium announcer relaying a wicket to every stand simultaneously, so all fans learn it at once.

LiveView vs. Traditional SPAs

Choosing LiveView over a traditional single-page app built with a JS framework trades client-side complexity for server-side state and network chattiness: there's no separate JSON API to design and version, and business logic lives in one place (Elixir), but every user interaction round-trips to the server over the WebSocket, meaning it's less suited for offline-first apps or scenarios with very high client-side interactivity per keystroke (though phx-debounce and JS hooks mitigate much of this).

🏏

Cricket analogy: Choosing LiveView over a traditional SPA is like choosing a live radio commentary feed over reading a printed scorecard you have to manually refresh.

LiveView's phx-click, phx-change, and phx-submit bindings cover most interactivity declaratively, but for cases needing real client-side behavior — like integrating a JS charting library or focusing an input — LiveView JS Hooks let you attach a JavaScript object with lifecycle callbacks (mounted, updated, destroyed) to a DOM element via phx-hook, bridging server state and client-only behavior cleanly.

  • LiveView renders UI server-side and upgrades the initial HTTP connection to a persistent WebSocket.
  • mount/3 initializes socket.assigns and runs once for the HTTP request and again for the WebSocket connect.
  • render/1 (or a .html.heex template) declares markup based on current assigns using HEEx syntax.
  • handle_event/3 responds to phx-click/phx-change/phx-submit bindings, updating assigns and triggering a diffed re-render.
  • Phoenix.PubSub.subscribe/2 and broadcast/3 enable multi-user real-time updates via handle_info/2.
  • LiveView trades a separate JSON API and client framework for server-rendered state and WebSocket round-trips.
  • JS Hooks (phx-hook) bridge server-driven state with client-only JavaScript behavior when needed.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#ElixirStudyNotes#ElixirAndLiveView#Elixir#LiveView#Phoenix#Lifecycle#StudyNotes#SkillVeris#ExamPrep