StarView behaviour (star_view v0.3.10)

Copy Markdown View Source

Elixir SDK helpers for Datastar.

The facade functions in this module delegate to small protocol modules while keeping a pipeline-friendly Plug API:

conn
|> StarView.start()
|> StarView.patch_signals(%{count: 1})
|> StarView.patch_elements(~s(<div id="count">1</div>))

Controller Behaviour

Use use StarView in your AppWeb.star_view/0 macro, then implement callbacks with @impl StarView:

Lifecycle

  1. mount/2 — Sets up initial signals and assigns for the page load.
  2. render/1 — Renders the HEEx template. Use init_signals/1 to emit the data-signals attribute for the initial client state.
  3. handle_event/3 — Called by StarView.Dispatch when a Datastar action fires. The dispatcher starts the SSE response before this callback, so signal/3 patches browser signals immediately.

Example

@impl StarView
def mount(conn, _params) do
  conn
  |> signal(:count, 0)
  |> signal(:step, 1)
end

@impl StarView
def render(assigns) do
  ~H"""
  <div data-signals={init_signals(@conn)}>
    <button data-on:click={post("increment")}>+</button>
    <span data-text="$count">{@count}</span>
  </div>
  """
end

@impl StarView
def handle_event("increment", signals, conn) do
  conn
  |> signal(:count, Map.get(signals, "count", 0) + 1)
end

Summary

Functions

Provides Phoenix controller helpers.

Checks whether a chunked SSE connection still accepts writes.

Logs a value to the browser console.

Executes JavaScript in the browser by appending a script element.

Patches one or more complete HTML elements into the DOM.

Patches client-side Datastar signals using RFC 7386 JSON Merge Patch semantics.

Patches client-side Datastar signals from a pre-encoded JSON string.

Reads Datastar signals from a Plug connection.

Reads Datastar signals from a Plug connection, raising on invalid JSON.

Redirects the browser by executing a tiny client-side script.

Removes elements from the DOM by CSS selector.

Removes signals by setting one or more dot-notated signal paths to null.

Sends a raw Datastar SSE event and returns the updated connection.

Starts a Server-Sent Events response on a Plug connection.

Starts an SSE stream with per-tab deduplication.

Callbacks

handle_event(t, map, t)

(optional)
@callback handle_event(String.t(), map(), Plug.Conn.t()) :: Plug.Conn.t()

mount(t, map)

@callback mount(Plug.Conn.t(), map()) :: Plug.Conn.t()

render(map)

@callback render(map()) :: term()

Functions

__using__(opts \\ [])

(macro)

Provides Phoenix controller helpers.

Use use StarView in your AppWeb.star_view/0 macro instead of use StarView.Controller directly:

def star_view do
  quote do
    use Phoenix.Controller, formats: [:html, :json]
    use StarView
    use Phoenix.Component

    use Gettext, backend: MyAppWeb.Gettext

    import Phoenix.Component, except: [assign: 3]
    import Plug.Conn

    unquote(verified_routes())
  end
end

check_connection(conn)

@spec check_connection(Plug.Conn.t()) ::
  {:ok, Plug.Conn.t()} | {:error, Plug.Conn.t()}

Checks whether a chunked SSE connection still accepts writes.

console_log(conn, message, opts \\ [])

@spec console_log(Plug.Conn.t(), term(), keyword()) :: Plug.Conn.t()

Logs a value to the browser console.

execute_script(conn, script, opts \\ [])

@spec execute_script(Plug.Conn.t(), String.t(), keyword()) :: Plug.Conn.t()

Executes JavaScript in the browser by appending a script element.

patch_elements(conn, elements, opts \\ [])

@spec patch_elements(Plug.Conn.t(), iodata() | tuple() | nil, keyword()) ::
  Plug.Conn.t()

Patches one or more complete HTML elements into the DOM.

patch_signals(conn, signals, opts \\ [])

@spec patch_signals(Plug.Conn.t(), map(), keyword()) :: Plug.Conn.t()

Patches client-side Datastar signals using RFC 7386 JSON Merge Patch semantics.

patch_signals_raw(conn, signals_json, opts \\ [])

@spec patch_signals_raw(Plug.Conn.t(), String.t(), keyword()) :: Plug.Conn.t()

Patches client-side Datastar signals from a pre-encoded JSON string.

read_signals(conn)

@spec read_signals(Plug.Conn.t()) :: map()

Reads Datastar signals from a Plug connection.

Returns a signal map. Raises StarView.Signals.ReadError when the payload cannot be decoded. Plugs that need {:ok, map()} | {:error, term()} should call StarView.Signals.read/1 instead.

read_signals!(conn)

@spec read_signals!(Plug.Conn.t()) :: map()

Reads Datastar signals from a Plug connection, raising on invalid JSON.

redirect(conn, url, opts \\ [])

@spec redirect(Plug.Conn.t(), String.t(), keyword()) :: Plug.Conn.t()

Redirects the browser by executing a tiny client-side script.

remove_elements(conn, selector, opts \\ [])

@spec remove_elements(Plug.Conn.t(), String.t(), keyword()) :: Plug.Conn.t()

Removes elements from the DOM by CSS selector.

remove_signals(conn, paths, opts \\ [])

@spec remove_signals(Plug.Conn.t(), String.t() | [String.t()], keyword()) ::
  Plug.Conn.t()

Removes signals by setting one or more dot-notated signal paths to null.

send(conn, event_type, data_lines, opts \\ [])

@spec send(Plug.Conn.t(), String.t(), [String.t()] | String.t(), keyword()) ::
  Plug.Conn.t()

Sends a raw Datastar SSE event and returns the updated connection.

start(conn)

@spec start(Plug.Conn.t()) :: Plug.Conn.t()

Starts a Server-Sent Events response on a Plug connection.

start_stream(conn, scope_key)

@spec start_stream(Plug.Conn.t(), term()) :: Plug.Conn.t()

Starts an SSE stream with per-tab deduplication.

Requires StarView.StreamRegistry in your supervision tree and a tabId signal in your root layout. See StarView.StreamRegistry for setup.