### Install UpChunk JS Library
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/external-uploads.md
Install the UpChunk library using npm for chunked HTTP uploads.
```shell
$ npm install --prefix assets --save @mux/upchunk
```
--------------------------------
### LiveSocket JavaScript Setup
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/introduction/welcome.md
Initializes the LiveSocket connection in the application's JavaScript entry point, enabling LiveView functionality.
```javascript
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
liveSocket.connect()
```
--------------------------------
### Run all end-to-end tests
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/test/e2e/README.md
Execute all end-to-end tests using the npm script. This command starts a LiveView server for testing.
```bash
npm run e2e:test
```
--------------------------------
### Install npm dependencies and Playwright browsers
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/test/e2e/README.md
Before running tests, install necessary npm packages and Playwright's browser binaries.
```bash
npm ci
npx playwright install
```
--------------------------------
### LiveComponent Handle Event Start Metadata
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Metadata for the [:phoenix, :live_component, :handle_event, :start] telemetry event. Includes event details and parameters.
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
component: atom,
event: String.t(),
params: unsigned_params
}
```
--------------------------------
### Install Polyfills for IE11 Support
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Use this npm command to install the required polyfills for IE11 compatibility. Ensure you specify the assets directory with the --prefix flag.
```shell
$ npm install --save --prefix assets mdn-polyfills url-search-params-polyfill formdata-polyfill child-replace-with-polyfill classlist-polyfill new-event-polyfill @webcomponents/template shim-keyboard-event-key core-js
```
--------------------------------
### LiveView Mount Start Telemetry Event
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Dispatched before the mount/3 callback. Includes system time for measurement and socket, params, session, and uri for metadata.
```elixir
[:phoenix, :live_view, :mount, :start]
```
```elixir
%{system_time: System.monotonic_time}
```
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
params: unsigned_params | :not_mounted_at_router,
session: map,
uri: String.t() | nil
}
```
--------------------------------
### Create a New Phoenix LiveView App
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Use the `mix phx.new` command to generate a new Phoenix application with LiveView pre-installed. Ensure you have the `phx_new` archive installed first.
```bash
$ mix archive.install hex phx_new
$ mix phx.new demo
```
--------------------------------
### LiveComponent Update Start Metadata
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Metadata for the [:phoenix, :live_component, :update, :start] telemetry event. Contains socket and component assignment details.
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
component: atom,
assigns_sockets: [{map(), Phoenix.LiveView.Socket.t}]
}
```
--------------------------------
### HTML Button with Click and Keydown Events
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Example of HTML elements with `phx-click` and `phx-window-keydown` attributes. LiveView will add `-loading` classes to these elements when events are pushed to the server.
```heex
```
--------------------------------
### Server-Pushed Event Example
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
Server pushes a 'highlight' event with an item ID. This is useful for drawing user attention to specific elements.
```heex
item.id} class="item">
{item.title}
```
```elixir
def handle_info({:item_updated, item}, socket) do
{:noreply, push_event(socket, "highlight", %{id: "item-" <> item.id})}
end
```
```javascript
let liveSocket = new LiveSocket(...)
window.addEventListener("phx:highlight", (e) => {
let el = document.getElementById(e.detail.id)
if(el) {
// logic for highlighting
}
})
```
--------------------------------
### LiveView Handle Params Start Telemetry Event
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Dispatched before the handle_params/3 callback. Measures the system time and includes metadata for the socket, params, and uri.
```elixir
[:phoenix, :live_view, :handle_params, :start]
```
```elixir
%{system_time: System.monotonic_time}
```
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
params: unsigned_params,
uri: String.t()
}
```
--------------------------------
### LiveView Mount Callback for Authorization
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Implement authorization logic within the `mount/3` callback to ensure users are authenticated and confirmed before proceeding. This example redirects unconfirmed users to the login page.
```elixir
def mount(_params, %{"user_id" => user_id} = _session, socket) do
socket = assign(socket, current_user: Accounts.get_user!(user_id))
socket =
if socket.assigns.current_user.confirmed_at do
socket
else
redirect(socket, to: "/login")
end
{:ok, socket}
end
```
--------------------------------
### S3 CORS Configuration Example
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/external-uploads.md
An example of CORS configuration for an S3 bucket to allow client-side uploads. Ensure 'AllowedOrigins' includes your application's domain.
```json
[
{
"AllowedHeaders": [ "*" ],
"AllowedMethods": [ "PUT", "POST" ],
"AllowedOrigins": [
"https://web.myapp.com",
// Add any other domains desired, or * for wildcard.
],
"ExposeHeaders": []
}
]
```
--------------------------------
### Run JavaScript End-to-End Tests
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Execute JavaScript end-to-end tests. Ensure all dependencies are installed before running.
```bash
$ mix deps.get
$ npm ci
$ npm run e2e:test
```
--------------------------------
### LiveView Render Start Telemetry Event
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Dispatched immediately before a render starts, which may involve Phoenix.LiveView.render/1 or Phoenix.LiveComponent.render/1 callbacks. Measures system time and includes socket, force?, and changed? metadata.
```elixir
[:phoenix, :live_view, :render, :start]
```
```elixir
%{system_time: System.monotonic_time}
```
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
force?: boolean,
changed?: boolean
}
```
```elixir
%{
component: module,
id: term,
cid: integer
}
```
--------------------------------
### LiveView Handle Event Start Telemetry Event
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Dispatched before the handle_event/3 callback. Measures the system time and includes metadata for the socket, event name, and params.
```elixir
[:phoenix, :live_view, :handle_event, :start]
```
```elixir
%{system_time: System.monotonic_time}
```
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
event: String.t(),
params: unsigned_params
}
```
--------------------------------
### Run All JavaScript Tests
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Execute all JavaScript tests. This involves fetching Elixir dependencies, installing Node.js dependencies, and running the npm test script.
```bash
$ mix deps.get
$ npm ci
$ npm test
```
--------------------------------
### Load LiveSocket for JS Interop
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
To enable JS Hooks and JS commands on regular pages, the page must load and connect `LiveSocket`. This setup is similar to a standard LiveView page.
```javascript
import {LiveSocket} from "phoenix_live_view"
const liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks})
liveSocket.connect()
```
--------------------------------
### Including Custom Metadata in Client Events
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Configure `LiveSocket` to send custom metadata with client events. This example sends click coordinates and `altKey` status for all clicks.
```javascript
let liveSocket = new LiveSocket("/live", Socket, {
params: {_csrf_token: csrfToken},
metadata: {
click: (e, el) => {
return {
altKey: e.altKey,
clientX: e.clientX,
clientY: e.clientY
}
}
}
})
```
--------------------------------
### Animate Element on Mount with phx-mounted
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Use the `phx-mounted` binding to trigger a JavaScript transition when an element is added to the DOM. This example uses `JS.transition` for a 'ping' animation.
```heex
```
--------------------------------
### Handling Click Events with phx-value- Attributes on Server
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Example of a server-side `handle_event` function that receives parameters from `phx-value-` attributes. The parameters are available as a map.
```elixir
def handle_event("inc", %{"myvar1" => "val1", "myvar2" => "val2"}, socket) do
end
```
--------------------------------
### Throttling Button Clicks
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Use `phx-throttle` to limit the rate of events like clicks. This example ensures the 'volume_up' event is sent at most once per second.
```heex
```
--------------------------------
### Import Polyfills in JavaScript
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Import the necessary polyfills into your application's JavaScript file to ensure compatibility with older browsers. This example shows the imports for Phoenix LiveView's app.js.
```javascript
// assets/js/app.js
import "mdn-polyfills/Object.assign"
import "mdn-polyfills/CustomEvent"
import "mdn-polyfills/String.prototype.startsWith"
import "mdn-polyfills/Array.from"
import "mdn-polyfills/Array.prototype.find"
import "mdn-polyfills/Array.prototype.some"
import "mdn-polyfills/NodeList.prototype.forEach"
import "mdn-polyfills/Element.prototype.closest"
import "mdn-polyfills/Element.prototype.matches"
import "mdn-polyfills/Node.prototype.remove"
import "child-replace-with-polyfill"
import "url-search-params-polyfill"
import "formdata-polyfill"
import "classlist-polyfill"
import "new-event-polyfill"
import "@webcomponents/template"
import "shim-keyboard-event-key"
import "event-submitter-polyfill"
import "core-js/features/set"
import "core-js/features/url"
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
...
```
--------------------------------
### Button with Tailwind Loading Variant Class
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Example of a button using a Tailwind CSS variant (`phx-click-loading:opacity-50`) to apply styling when the element is in a loading state. This leverages the Tailwind integration for dynamic styling.
```heex
```
--------------------------------
### Initialize Uploads in LiveView Mount
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/uploads.md
Use `allow_upload/3` in the `mount` function to configure upload specifications like accepted file types and maximum entries. This sets up the upload handling for a specific upload reference.
```elixir
iex> @impl Phoenix.LiveView
def mount(_params, _session, socket) do
{:ok,
socket
|> assign(:uploaded_files, [])
|> allow_upload(:avatar, accept: ~w(.jpg .jpeg), max_entries: 2)}
end
```
--------------------------------
### Live sorting with handle_params
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/live-navigation.md
Implement live sorting by using `patch` links and handling URL parameters in the `handle_params/3` callback. This allows updating the LiveView state based on URL changes without remounting.
```heex
<.link patch={~p"/users?sort_by=name"}>Sort by name
```
--------------------------------
### Mount and Paginate Posts
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Initializes the LiveView by assigning pagination state and fetching the first page of posts. This function is responsible for fetching data and updating the stream.
```elixir
def mount(_, _, socket) do
{:ok,
socket
|> assign(page: 1, per_page: 20)
|> paginate_posts(1)}
end
defp paginate_posts(socket, new_page) when new_page >= 1 do
%{per_page: per_page, page: cur_page} = socket.assigns
posts = Blog.list_posts(offset: (new_page - 1) * per_page, limit: per_page)
{posts, at, limit} =
if new_page >= cur_page do
{posts, -1, per_page * 3 * -1}
else
{Enum.reverse(posts), 0, per_page * 3}
end
case posts do
[] ->
assign(socket, end_of_timeline?: at == -1)
[_ | _] = posts ->
socket
|> assign(end_of_timeline?: false)
|> assign(:page, new_page)
|> stream(:posts, posts, at: at, limit: limit)
end
end
```
--------------------------------
### Customize JS Push Event with Options
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Shows how to customize a `JS.push` command with options like `target` and `loading` to control server interaction and client-side feedback.
```heex
```
--------------------------------
### Run Elixir Tests
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Execute Elixir tests by first fetching dependencies and then running the test suite.
```bash
$ mix deps.get
$ mix test
```
--------------------------------
### Router Configuration with `on_mount` Hook
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Configure the `on_mount` hook in the router's `live_session` to apply authentication logic to all LiveViews within that session.
```elixir
live_session :default, on_mount: MyAppWeb.UserLiveAuth do
# Your routes
end
```
--------------------------------
### LiveView Mount and Presign Upload Function
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/external-uploads.md
Implements the LiveView mount function to allow external uploads and defines the presign_upload function to generate pre-signed S3 URLs. Ensure the SimpleS3Upload module is available.
```elixir
def mount(_params, _session, socket) do
{:ok,
socket
|> assign(:uploaded_files, [])
|> allow_upload(:avatar, accept: :any, max_entries: 3, external: &presign_upload/2)}
end
defp presign_upload(entry, socket) do
uploads = socket.assigns.uploads
bucket = "phx-upload-example"
key = "public/#{entry.client_name}"
config = %{
region: "us-east-1",
access_key_id: System.fetch_env!("AWS_ACCESS_KEY_ID"),
secret_access_key: System.fetch_env!("AWS_SECRET_ACCESS_KEY")
}
{:ok, fields} =
SimpleS3Upload.sign_form_upload(config, bucket,
key: key,
content_type: entry.client_type,
max_file_size: uploads[entry.upload_config].max_file_size,
expires_in: :timer.hours(1)
)
meta = %{uploader: "S3", key: key, url: "http://#{bucket}.s3-#{config.region}.amazonaws.com", fields: fields}
{:ok, meta, socket}
end
```
--------------------------------
### Integrating Colocated Hooks in app.js
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
Import colocated hooks from the `phoenix-colocated` package into your `app.js` to make them available to LiveView. This example shows the import and hook merging.
```diff
...
import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"
import topbar from "../vendor/topbar"
+ import {hooks as colocatedHooks} from "phoenix-colocated/my_app"
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
longPollFallbackMs: 2500,
params: {_csrf_token: csrfToken},
+ hooks: {...colocatedHooks}
})
```
--------------------------------
### Show Modal with Fade-in Transition
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Demonstrates how to show a modal element with a fade-in transition using `JS.show`.
```heex
My Modal
```
--------------------------------
### Mount LiveView with Upload Component
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/uploads.md
Initializes the LiveView socket with upload capabilities for a specific input. Configure accepted file types and maximum entries.
```elixir
defmodule MyAppWeb.UploadLive do
use MyAppWeb, :live_view
@impl Phoenix.LiveView
def mount(_params, _session, socket) do
{:ok,
socket
|> assign(:uploaded_files, [])
|> allow_upload(:avatar, accept: ~w(.jpg .jpeg), max_entries: 2)}
end
@impl Phoenix.LiveView
def handle_event("validate", _params, socket) do
{:noreply, socket}
end
@impl Phoenix.LiveView
def handle_event("cancel-upload", %{"ref" => ref}, socket) do
{:noreply, cancel_upload(socket, :avatar, ref)}
end
@impl Phoenix.LiveView
def handle_event("save", _params, socket) do
uploaded_files =
consume_uploaded_entries(socket, :avatar, fn %{path: path}, _entry ->
dest = Path.join([:code.priv_dir(:my_app), "static", "uploads", Path.basename(path)])
# You will need to create `priv/static/uploads` for `File.cp!/2` to work.
File.cp!(path, dest)
{:ok, ~p"/uploads/#{Path.basename(dest)}"}
end)
{:noreply, update(socket, :uploaded_files, &(&1 ++ uploaded_files))}
end
defp error_to_string(:too_large), do: "Too large"
defp error_to_string(:too_many_files), do: "You have selected too many files"
defp error_to_string(:not_accepted), do: "You have selected an unacceptable file type"
end
```
```
--------------------------------
### Default `live_view` Configuration with `on_mount` Hook
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Apply an `on_mount` hook to all LiveViews by default by defining it within the `MyAppWeb.live_view` function.
```elixir
def live_view do
quote do
use Phoenix.LiveView
on_mount MyAppWeb.UserLiveAuth
unquote(html_helpers())
end
end
```
--------------------------------
### Colocated Hook in HEEx Component
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
Define JavaScript logic directly within HEEx components using `Phoenix.LiveView.ColocatedHook`. This example shows an input hook that formats phone numbers.
```elixir
def phone_number_input(assigns) do
~H"""
"""
end
```
--------------------------------
### Live Session with Router-Level on_mount Hook
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Configure `live_session` with an `on_mount` option to enforce authentication hooks at the router level for all LiveViews within that session. This avoids repeating the hook on every LiveView.
```elixir
scope "/" do
pipe_through [:authenticate_user]
live_session :default, on_mount: MyAppWeb.UserLiveAuth do
live ...
end
end
scope "/admin" do
pipe_through [:authenticate_admin]
live_session :admin, on_mount: MyAppWeb.AdminLiveAuth do
live ...
end
end
```
--------------------------------
### Render File Input with LiveFileComponent
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/uploads.md
Use the `live_file_input/1` component to render a file input element. Attributes like `id`, `accept`, and `multiple` are automatically set based on the `allow_upload/3` specification.
```heex
<%!-- lib/my_app_web/live/upload_live.html.heex --%>
```
--------------------------------
### Format Files
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Format both Elixir and JavaScript files according to project standards.
```bash
$ mix format
$ npm run js:format
```
--------------------------------
### Thermostat LiveView Module
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/introduction/welcome.md
Defines a basic LiveView with render, mount, and handle_event callbacks to manage and display a temperature. Uses HEEx for templating.
```elixir
defmodule MyAppWeb.ThermostatLive do
use MyAppWeb, :live_view
def render(assigns) do
~H"""
Current temperature: {@temperature}°F
"""
end
def mount(_params, _session, socket) do
temperature = 70 # Let's assume a fixed temperature for now
{:ok, assign(socket, :temperature, temperature)}
end
def handle_event("inc_temperature", _params, socket) do
{:noreply, update(socket, :temperature, &(&1 + 1))}
end
end
```
--------------------------------
### Use Live Title Component
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/live-layouts.md
Utilize the `live_title` component for automatic prefixing and suffixing of the page title, supporting dynamic updates.
```heex
{assigns[:page_title]}
```
--------------------------------
### LiveView Module Configuration with `on_mount` Hook
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Specify an `on_mount` hook directly within a specific LiveView module to apply authentication logic only to that LiveView.
```elixir
defmodule MyAppWeb.PageLive do
use MyAppWeb, :live_view
on_mount MyAppWeb.UserLiveAuth
...
end
```
--------------------------------
### LiveView `on_mount` Hook for Authentication
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Encapsulate authentication and authorization logic in an `on_mount` hook for reusable execution on every LiveView mount. This hook fetches the user by session token and halts if the user is not confirmed.
```elixir
defmodule MyAppWeb.UserLiveAuth do
import Phoenix.Component
import Phoenix.LiveView
alias MyAppWeb.Accounts # from `mix phx.gen.auth`
def on_mount(:default, _params, %{"user_token" => user_token} = _session, socket) do
socket =
assign_new(socket, :current_user, fn ->
Accounts.get_user_by_session_token(user_token)
end)
if socket.assigns.current_user.confirmed_at do
{:cont, socket}
else
{:halt, redirect(socket, to: "/login")}
end
end
end
```
--------------------------------
### Read Both Parameters and Session in Mount
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/introduction/welcome.md
Combines reading both 'house' from parameters and 'current_user_id' from the session to fetch specific thermostat data. This is a common pattern for authenticated, context-aware data retrieval.
```elixir
def mount(%{"house" => house}, %{"current_user_id" => user_id}, socket) do
temperature = Thermostat.get_house_reading(user_id, house)
{:ok, assign(socket, :temperature, temperature)}
end
```
--------------------------------
### Display Page Loading Status with Topbar
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Listen for 'phx:page-loading-start' and 'phx:page-loading-stop' events on the window to show and hide a loading indicator like topbar. This is useful for providing visual feedback during navigation.
```javascript
import topbar from "topbar"
window.addEventListener("phx:page-loading-start", info => topbar.show(500))
window.addEventListener("phx:page-loading-stop", info => topbar.hide())
```
--------------------------------
### Client State During Submit and Server Processing
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Shows the client's UI state after the user finishes typing and presses submit, while a server debounce event is still being processed.
```plain_text
[ hello@example.com ]
------------
SUBMITTING
------------
```
--------------------------------
### Show Modal by Adding Class
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Shows a modal by adding a 'show' class to the element with a fade-in transition using `JS.add_class`.
```heex
My Modal
```
--------------------------------
### Target Param for Input Change
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/form-bindings.md
Shows how the _target param is structured in the server's handle_event/3 when an input triggers a change event. The keyspace of the input name is included.
```heex
```
```Elixir
%{"_target" => ["user", "username"], "user" => %{"username" => "Name"}}
```
--------------------------------
### Testing Viewport Events with render_hook
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Demonstrates how to test viewport events in a LiveView using `Phoenix.LiveViewTest.render_hook/3`.
```elixir
view
|> element("#posts")
|> render_hook("next-page")
```
--------------------------------
### Configure Uploads in LiveView Mount
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/external-uploads.md
Configure the LiveView mount function to allow external uploads, specifying an external function for generating signed URLs.
```elixir
def mount(_params, _session, socket) do
{:ok,
socket
|> assign(:uploaded_files, [])
|> allow_upload(:avatar, accept: :any, max_entries: 3, external: &presign_upload/2)}
end
```
--------------------------------
### Button Binding for Client-Server Interaction
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/introduction/welcome.md
Renders a button with a 'phx-click' binding that triggers the 'inc_temperature' event on the server when clicked.
```html
```
--------------------------------
### Client State Before Server Response
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Illustrates the client's UI state when an email input is partially typed and a debounce event is in flight.
```plain_text
[ hello@example. ]
------------
SUBMIT
------------
```
--------------------------------
### Client-side navigation with link component
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/live-navigation.md
Use `patch` or `navigate` attributes in the `Phoenix.Component.link/1` component to trigger live navigation from the client. `patch` updates the current LiveView, while `navigate` mounts a new one.
```heex
<.link patch={~p"/pages/#{@page + 1}"}>Next
```
--------------------------------
### HEEx Comprehension with `:key` for Optimized Tracking
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/assigns-eex.md
When using comprehensions, specify a `:key` attribute (e.g., `post.id`) to help LiveView track changes more efficiently within the collection, especially for insertions or deletions.
```heex
{expand_title(post.title)}
```
--------------------------------
### LiveView Server Callbacks for Form Recovery
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/form-bindings.md
Implement `handle_event` callbacks on the server to handle form validation and custom recovery logic. The `validate_wizard_step` handles current step validations, while `recover_wizard` rebuilds state based on client input.
```elixir
def handle_event("validate_wizard_step", params, socket) do
# regular validations for current step
{:noreply, socket}
end
def handle_event("recover_wizard", params, socket) do
# rebuild state based on client input data up to the current step
{:noreply, socket}
end
```
--------------------------------
### Handle Form Reset Event
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/form-bindings.md
Demonstrates how to handle a form reset event on the server. A phx-change event is emitted with a _target param indicating the reset name.
```heex
```
```Elixir
def handle_event("changed", %{"_target" => ["reset"]} = params, socket) do
# handle form reset
end
def handle_event("changed", params, socket) do
# handle regular form change
end
```
--------------------------------
### Handle Next and Previous Page Events
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Handles 'next-page' and 'prev-page' events to update pagination and fetch new posts. It includes logic to reset to the first page if the viewport is overrun.
```elixir
def handle_event("next-page", _, socket) do
{:noreply, paginate_posts(socket, socket.assigns.page + 1)}
end
def handle_event("prev-page", %{"_overran" => true}, socket) do
{:noreply, paginate_posts(socket, 1)}
end
def handle_event("prev-page", _, socket) do
if socket.assigns.page > 1 do
{:noreply, paginate_posts(socket, socket.assigns.page - 1)}
else
{:noreply, socket}
end
end
```
--------------------------------
### Basic Form with Change and Submit Bindings
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/form-bindings.md
Use `phx-change` and `phx-submit` on a form component to handle input changes and form submissions. The form is rendered using the `.form` function component.
```heex
<.form for={@form} id="my-form" phx-change="validate" phx-submit="save">
<.input type="text" field={@form[:username]} />
<.input type="email" field={@form[:email]} />
```
--------------------------------
### Run JavaScript Unit Tests
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Execute JavaScript unit tests. Includes an option to automatically run tests for changed files.
```bash
$ mix deps.get
$ npm ci
$ npm run js:test
# to automatically run tests for files that have been changed
$ npm run js:test.watch
```
--------------------------------
### Pushing Events to LiveView with Reply Callback
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
Use `pushEvent` within a hook to send data to the LiveView and handle a reply using a callback function. The server must respond with `{:reply, map, socket}`.
```heex
Click me for a message!
```
```javascript
Hooks.ClickMeHook = {
mounted() {
this.el.addEventListener("click", () => {
// Push event to LiveView with callback for reply
this.pushEvent("get_message", {}, (reply) => {
console.debug(reply.message);
});
});
}
}
```
```elixir
def handle_event("get_message", _params, socket) do
# Use :reply to respond to the pushEvent
{:reply, %{message: "Hello from LiveView!"}, socket}
end
```
--------------------------------
### Simulate Network Latency in LiveView
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
Use the enableLatencySim function on the LiveSocket instance to simulate network latency for testing UX. The function accepts an integer in milliseconds for the one-way latency. Debug state persists for the browser session.
```javascript
// app.js
let liveSocket = new LiveSocket(...)
liveSocket.connect()
window.liveSocket = liveSocket
// in the browser's web console
>> liveSocket.enableLatencySim(1000)
[Log] latency simulator enabled for the duration of this browser session.
Call disableLatencySim() to disable
```
--------------------------------
### HEEx Comprehension with `for`
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/assigns-eex.md
Use `for` within HEEx templates to iterate over lists and collections. LiveView optimizes static parts and tracks changes within the collection.
```heex
<%= for post <- @posts do %>
{expand_title(post.title)}
<% end %>
```
--------------------------------
### Server-side navigation with push_patch
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/live-navigation.md
Trigger live navigation from the server using `Phoenix.LiveView.push_patch/2`. This is useful for updating the current LiveView's URL and parameters without a full page reload.
```elixir
{:noreply, push_patch(socket, to: ~p"/pages/#{@page + 1}")}
```
--------------------------------
### Defining Live Sessions with Different Authentication
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
Use `live_session` to group LiveViews and specify different authentication pipelines for distinct user scopes. This ensures that navigation events within the same session skip HTTP requests.
```elixir
scope "/" do
pipe_through [:authenticate_user]
get ...
live_session :default do
live ...
end
end
scope "/admin" do
pipe_through [:http_auth_admin]
get ...
live_session :admin do
live ...
end
end
```
--------------------------------
### Run specific test in headed mode
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/test/e2e/README.md
Execute a particular test file and line number in headed mode, targeting a specific browser project.
```bash
npm run e2e:test -- tests/streams.spec.js:9 --project chromium --headed
```
--------------------------------
### Apply Loading State to Specific Element
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Use `JS.push` with a `loading` option to apply a loading state to a specific element identified by a selector, rather than just the clicked element.
```heex
```
--------------------------------
### LiveSocket Configuration with Uploaders
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/external-uploads.md
Configures the LiveSocket in app.js to include the custom uploaders. This step connects the server-side metadata uploader name ('S3') with the client-side JavaScript implementation.
```javascript
// for uploading to S3
import Uploaders from "./uploaders"
let liveSocket = new LiveSocket("/live",
Socket, {
params: {_csrf_token: csrfToken},
uploaders: Uploaders
}
)
```
--------------------------------
### Render a LiveComponent
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/introduction/welcome.md
LiveComponents encapsulate state, markup, and events. They are rendered using the `live_component/1` function and have their own callbacks.
```heex
<.live_component module={UserComponent} id={user.id} user={user} />
```
--------------------------------
### Display Upload Entries and Progress
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/uploads.md
Iterate over upload entries using `entry <- @uploads.avatar.entries` to display file information, progress bars, and handle cancellation. Use `upload_errors/2` and `upload_errors/1` to show specific entry or general upload errors.
```heex
<%!-- lib/my_app_web/live/upload_live.html.heex --%>
<%!-- use phx-drop-target with the upload ref to enable file drag and drop --%>
<%!-- render each avatar entry --%>
<.live_img_preview entry={entry} />
{entry.client_name}
<%!-- entry.progress will update automatically for in-flight entries --%>
<%!-- a regular click event whose handler will invoke Phoenix.LiveView.cancel_upload/3 --%>
<%!-- Phoenix.Component.upload_errors/2 returns a list of error atoms --%>
{error_to_string(err)}
<%!-- Phoenix.Component.upload_errors/1 returns a list of error atoms --%>
{error_to_string(err)}
```
--------------------------------
### Toggle Modal with Transitions
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Demonstrates how to toggle the visibility of a modal element with specified in and out transitions using `JS.toggle`.
```heex
My Modal
```
--------------------------------
### Authorize User Actions in handle_event
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/security-model.md
This snippet shows how to authorize a user within a `handle_event` callback before performing a sensitive action like deleting a project. It ensures that even if a user bypasses UI restrictions, the server-side permission check prevents unauthorized operations.
```elixir
on_mount MyAppWeb.UserLiveAuth
def mount(_params, _session, socket) do
{:ok, load_projects(socket)}
end
def handle_event("delete_project", %{"project_id" => project_id}, socket) do
Project.delete!(socket.assigns.current_scope, project_id)
{:noreply, update(socket, :projects, &Enum.reject(&1, fn p -> p.id == project_id end))}
end
defp load_projects(socket) do
projects = Project.all_projects(socket.assigns.current_scope)
assign(socket, projects: projects)
end
```
--------------------------------
### Enable Debug Logging for LiveView Client Events
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/js-interop.md
Expose the LiveSocket instance on the window object to enable debug logging in the browser's web console. This helps in troubleshooting by showing LiveView lifecycle and payload events.
```javascript
// app.js
let liveSocket = new LiveSocket(...)
liveSocket.connect()
window.liveSocket = liveSocket
// in the browser's web console
>> liveSocket.enableDebug()
```
--------------------------------
### Check Test Coverage
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/README.md
Generate and report on test coverage for JavaScript code.
```bash
$ npm run cover
$ npm run cover:report
```
--------------------------------
### Set Root Layout in Router
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/live-layouts.md
Configure the root layout for your LiveView application within the router configuration.
```elixir
plug :put_root_layout, html: {MyAppWeb.Layouts, :root}
```
--------------------------------
### LiveView Event Handling for Form Events
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/form-bindings.md
Implement `handle_event` callbacks in your LiveView to process 'validate' and 'save' events triggered by the form. This includes updating the changeset, creating a user, and handling errors.
```elixir
def mount(_params, _session, socket) do
{:ok, assign(socket, form: to_form(Accounts.change_user(%User{})))}
end
def handle_event("validate", %{"user" => params}, socket) do
form =
%User{}
|> Accounts.change_user(params)
|> to_form(action: :validate)
{:noreply, assign(socket, form: form)}
end
def handle_event("save", %{"user" => user_params}, socket) do
case Accounts.create_user(user_params) do
{:ok, user} ->
{:noreply,
socket
|> put_flash(:info, "user created")
|> redirect(to: ~p"/users/#{user}")}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, form: to_form(changeset))}
end
end
```
--------------------------------
### Generate Presigned Upload URL
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/external-uploads.md
Implement the external upload function to generate a presigned URL for direct uploads to cloud storage.
```elixir
defp presign_upload(entry, socket) do
{:ok, %{"Location" => link}} =
SomeTube.start_session(%{
"uploadType" => "resumable",
"x-upload-content-length" => entry.client_size
})
{:ok, %{uploader: "UpChunk", entrypoint: link}, socket}
end
```
--------------------------------
### Sending Values with phx-value- Attributes
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Utilize `phx-value-` prefixed attributes to send multiple key-value pairs with a click event. The server receives these as a map.
```heex
```
--------------------------------
### Configuring Keydown Metadata for LiveSocket
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/bindings.md
Customize the metadata sent to the server for keydown events by providing a metadata function to the LiveSocket constructor. This allows capturing specific keyboard event properties.
```javascript
let liveSocket = new LiveSocket("/live", Socket, {
params: {_csrf_token: csrfToken},
metadata: {
keydown: (e, el) => {
return {
key: e.key,
metaKey: e.metaKey,
repeat: e.repeat
}
}
}
})
```
--------------------------------
### Assign Data in LiveView
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/assigns-eex.md
Load data in your LiveView and assign it using `assign/2` before rendering the template. This ensures LiveView can track changes to the data.
```elixir
assign(socket, :users, Repo.all(User))
```
--------------------------------
### Implement Minimal Validation Callback
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/uploads.md
A minimal `handle_event/3` callback is required to trigger upload validation when using `phx-change` on a form. This function must be implemented to perform entry validation.
```elixir
@impl Phoenix.LiveView
def handle_event("validate", _params, socket) do
{:noreply, socket}
end
```
--------------------------------
### Retrieve and Set Gettext Locale from Database in LiveView Mount
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/gettext.md
Retrieves the user's locale from the database based on user_id from the session and sets it for Gettext. This is suitable for applications where user locale preferences are stored persistently.
```elixir
def mount(_params, %{"user_id" => user_id}, socket) do
user = Users.get_user!(user_id)
Gettext.put_locale(MyApp.Gettext, user.locale)
{:ok, socket}
end
```
--------------------------------
### Generate LiveView CRUD Interface
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/introduction/welcome.md
Generates a full CRUD interface for a LiveView resource, including database schema, migrations, and LiveView modules. Use this to quickly scaffold new LiveView applications.
```shell
mix phx.gen.live Blog Post posts title:string body:text
```
--------------------------------
### Use Function Components in LiveView
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/assigns-eex.md
Render reusable UI components using function components. LiveView tracks changes to the attributes passed to these components.
```heex
<.show_name name={@user.name} />
```
--------------------------------
### LiveView Render Exception Metadata
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/telemetry.md
Metadata for the [:phoenix, :live_view, :render, :exception] telemetry event. Includes socket information, reason for exception, and optional rendering details.
```elixir
%{
socket: Phoenix.LiveView.Socket.t,
kind: atom,
reason: term,
force?: boolean,
changed?: boolean
}
```
--------------------------------
### Apply CSS Transition to Element
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/syncing-changes.md
Employ `JS.transition` to apply CSS transitions like 'shake' to a specified element, adding visual flair to user interactions.
```heex
My Item
```
--------------------------------
### Compute and Assign Values in LiveView Render
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/server/assigns-eex.md
Instead of defining local variables for computed values in the `render` function, use `assign/2` to store them. This allows LiveView to track changes to these computed values.
```elixir
def render(assigns) do
sum = assigns.x + assigns.y
title = assigns.title
~H"""
{title}
{sum}
"""
end
```
--------------------------------
### Reactive File Input with Drag and Drop
Source: https://github.com/phoenixframework/phoenix_live_view/blob/main/guides/client/form-bindings.md
LiveView forms support reactive file inputs, including drag and drop via the `phx-drop-target` attribute. Use `live_file_input` for uploads.
```heex