Skip to main content

Phoenix LiveView Tutorial: Getting Started

Nimrod Kramer Nimrod Kramer
Link copied!
Phoenix LiveView Tutorial: Getting Started
Quick take

Learn how to build interactive, real-time web applications with Phoenix LiveView using Elixir and Phoenix. Get started with key components, core concepts, best practices, and tips for better LiveView apps.

Phoenix LiveView is a powerful tool for building interactive, real-time web applications using Elixir and Phoenix. Here's what you need to know:

  • Purpose: Create fast, scalable web apps with real-time updates
  • Key Components:
    • mount function: Sets up initial state
    • handle_event function: Responds to user actions
    • render function: Displays updated view

Quick Setup:

  1. Install Elixir and Phoenix
  2. Create a new Phoenix project
  3. Add LiveView to your project
  4. Build your first LiveView module

Core Concepts:

  • DOM element bindings (e.g., phx-click)
  • Form handling and file uploads
  • Page navigation without reloading
  • Function components and LiveComponents

Best Practices:

Feature

Phoenix

Phoenix LiveView

Updates

Full page reload

Real-time, partial updates

Best for

Traditional web apps

Interactive, real-time apps

Process

New process per request

One process per WebSocket

This tutorial will guide you through setting up and using Phoenix LiveView to create dynamic, responsive web applications.

2. Before You Start

2.1 Installing Elixir and Phoenix

Elixir

To begin with Phoenix LiveView, you need Elixir and Phoenix on your computer. Here's how to set them up:

  1. Install Elixir
  1. Install Phoenix
  • Open your terminal
  • Run this command: mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez

To check if everything is set up correctly, create a new Phoenix project:

  • In your terminal, type: mix phx.new my_app (replace "my_app" with any name you like)

2.2 What You Need to Know

To use Phoenix LiveView well, you should understand:

Topic

Description

Elixir basics

Data types, functions, modules

Phoenix framework

Routing, controllers, templates

Web development

HTTP requests, responses, HTML, CSS, JavaScript

If you're new to Elixir or Phoenix, start with these learning resources:

These will help you build a good base before you start with LiveView.

3. Creating a New Phoenix Project

3.1 Setting Up Your Project

Let's create a new Phoenix project for your LiveView application. Open your terminal and run:

mix phx.new my_app

Replace my_app with your preferred name.

This command creates a new directory with the basic Phoenix structure:

Directory

Purpose

lib

Application code

test

Tests

priv

Static assets and private files

config

Application configuration

3.2 Adding LiveView to Your Project

To use LiveView, add it to your project:

  1. Open mix.exs and add this line to the deps function:
defp deps do
  [
    #...
    {:phoenix_live_view, "~> 0.17.5"},
    #...
  ]
end
  1. Install the dependency:
mix deps.get
  1. Set up LiveView in config/config.exs. Add these lines to the config function:
config :my_app, MyAppWeb.Endpoint,
  live_view: [
    signing_salt: "your_secret_salt"
  ]

Replace your_secret_salt with a secret of your choice.

You've now set up LiveView in your Phoenix project. Next, we'll look at how LiveView works.

4. LiveView Basics

4.1 How LiveView Works

LiveView helps build interactive web apps that update in real-time. Here's how it works:

  1. User does something (like clicking a button)
  2. This action changes the app's state
  3. LiveView updates the relevant parts of the web page
  4. The browser shows these updates without reloading the whole page

This process makes web apps feel quick and responsive.

Step

Description

  1. Event

User interacts with the app

  1. State Change

App's data updates

  1. Re-render

LiveView updates affected parts

  1. Browser Update

Changes appear on screen

4.2 Main LiveView Functions

LiveView uses three key functions:

Function

Purpose

mount/3

Sets up the initial state and view

handle_event/3

Responds to user actions

render/1

Shows the updated view

These functions work together to create a smooth, interactive experience for users.

5. Building Your First LiveView

5.1 Creating a LiveView Module

To start your first LiveView, make a LiveView module. This module has functions that control how your LiveView works. Here's how to create one:

defmodule MyAppWeb.ThermostatLive do
  use Phoenix.LiveView
  #...
end

5.2 Writing the render Function

The render/1 function shows the HTML for your LiveView. It takes one argument, assigns, which is a map of values for the template.

Here's an example:

def render(assigns) do
  ~H"""
  Current temperature: <%= @temperature %>ยฐF
  <button phx-click="inc_temperature">+</button>
  """
end

This function shows the current temperature and a button to increase it.

5.3 Using ~H for HTML Templates

The ~H sigil helps you write HTML templates. It uses a syntax like HTML.

Example:

~H"""
<div>
  <h1>Hello World!</h1>
  <p>This is a paragraph of text.</p>
</div>
"""

This creates a div with an h1 and a p element inside.

Function

Purpose

Example

use Phoenix.LiveView

Sets up LiveView in your module

use Phoenix.LiveView

render/1

Shows HTML for your LiveView

def render(assigns) do ... end

~H sigil

Writes HTML templates

~H"""<div>...</div>"""

6. Setting Up Initial State

6.1 The mount Function Explained

The mount/3 function in Phoenix LiveView sets up the starting state of your LiveView. It runs when the LiveView first loads and takes three inputs:

Input

Description

params

A map of parameters sent to the LiveView

session

The current session

socket

The LiveView socket

Here's a basic example:

def mount(params, session, socket) do
  {:ok, assign(socket, temperature: 20)}
end

This sets the starting temperature to 20 degrees.

6.2 Setting Up Starting Data

You can get data from a database or API in the mount/3 function. Here's how to do it with Ecto:

def mount(params, session, socket) do
  temperature = Repo.get_by(Temperature, id: 1)
  {:ok, assign(socket, temperature: temperature.value)}
end

This gets the temperature with ID 1 from the database and sets it in the socket.

You can also handle errors in mount/3. For example:

def mount(params, session, socket) do
  try do
    temperature = Repo.get_by(Temperature, id: 1)
    {:ok, assign(socket, temperature: temperature.value)}
  rescue
    e in Ecto.NoResultsError ->
      {:ok, assign(socket, temperature: 20)}
  end
end

If the database doesn't have a temperature with ID 1, this sets a default of 20 degrees.

Function

Purpose

mount/3

Sets up starting state

assign/2

Adds data to the socket

Repo.get_by/2

Gets data from the database

These tools help you set up your LiveView with the right starting data.

7. Responding to User Actions

7.1 Using handle_event

The handle_event/3 function in Phoenix LiveView responds to user actions. It takes three inputs:

Input

Description

event

Name of the event

params

Map of parameters sent with the event

socket

LiveView socket

Here's a basic example:

def handle_event("click", %{"id" => id}, socket) do
  # Handle the click event
  {:noreply, socket}
end

This function runs when a user clicks a button with the event name "click".

7.2 Changing State After User Input

To update the LiveView state after user input, use the assign/2 function:

def handle_event("text-entered", %{"text" => text}, socket) do
  {:noreply, assign(socket, text: text)}
end

This updates the text field in the socket when the user enters text.

You can also send events to the client with push_event/2:

def handle_event("text-entered", %{"text" => text}, socket) do
  {:noreply, push_event(socket, "text-entered", %{text: text})}
end

This sends an event to the client with the name "text-entered" and the entered text.

Function

Purpose

handle_event/3

Responds to user actions

assign/2

Updates LiveView state

push_event/2

Sends events to the client

Example:

Let's say you're making a LiveView for users to enter their name and age. When they click "Submit", you want to update the LiveView state:

def handle_event("submit", %{"name" => name, "age" => age}, socket) do
  {:noreply, assign(socket, name: name, age: age)}
end

This code updates the LiveView state with the entered name and age when the user clicks "Submit".

sbb-itb-bfaad5b

8. Using LiveView Bindings

8.1 What Are DOM Element Bindings?

DOM element bindings in Phoenix LiveView let you connect events to HTML elements. This helps you respond to user actions like clicks or typing, and update your LiveView state.

Bindings use the phx- prefix followed by the event name. For example, phx-click connects a click event to an element. These bindings trigger events on the server, which can then change the LiveView state.

8.2 Common Binding Examples

Here's a table of common bindings:

Binding

What it does

phx-click

Responds to clicks

phx-submit

Responds to form submissions

phx-keyup

Responds when a key is released

phx-keydown

Responds when a key is pressed

phx-blur

Responds when an element loses focus

phx-focus

Responds when an element gains focus

You can use these bindings on different HTML elements. For example:

<button phx-click="submit">Submit</button>

This code makes the button trigger a "submit" event on the server when clicked.

You can also use bindings on larger elements:

<div phx-window-keyup="handle-keyup">
  <input type="text" />
  <button>Submit</button>
</div>

This code makes the whole div respond to key releases, triggering a "handle-keyup" event on the server.

9. Working with Forms

9.1 Building and Processing Forms

Forms are key in web apps. Phoenix LiveView makes form handling easy. Here's how to build and process forms in LiveView:

To create a form, use the form function from Phoenix.HTML. This function needs:

  • The form's submit URL
  • The method (like :post or :get)
  • Any extra form attributes

Here's a simple form example:

def render(assigns) do
  ~H"""
  <form phx-submit="submit">
    <input type="text" name="name" />
    <input type="submit" value="Submit" />
  </form>
  """
end

This form has a text input and a submit button. The phx-submit attribute sets the event for form submission.

To handle the form data, use the handle_event function in your LiveView module:

def handle_event("submit", %{"name" => name}, socket) do
  # Process the form data here
  {:noreply, socket}
end

This function takes the event name and form data as inputs. It processes the data and returns a tuple.

9.2 Handling File Uploads

File uploads in LiveView need a bit more work, but it's not too hard. Use the Phoenix.LiveView.Upload module for this.

Here's how to handle a file upload:

def render(assigns) do
  ~H"""
  <form phx-submit="upload">
    <input type="file" name="file" />
    <input type="submit" value="Upload" />
  </form>
  """
end

def handle_event("upload", %{"file" => file}, socket) do
  # Process the file upload here
  {:noreply, socket}
end

This form has a file input and a submit button. The upload event handles the file data.

Step

Description

1

Create a form with a file input

2

Set up an event handler for the upload

3

Process the file data in the handler

4

Return a tuple to show the event is handled

10. Page Navigation

10.1 Changing Pages Without Reloading

Phoenix LiveView lets you change pages without reloading the whole page. This makes your app feel faster. You can use the live_redirect function to do this.

Here's how to use live_redirect:

def handle_event("go_to_next_page", _, socket) do
  {:noreply, live_redirect(socket, to: "/next_page")}
end

This code sends the user to "/next_page" without reloading the page when the "go_to_next_page" event happens.

10.2 Updating vs. Loading New LiveViews

When moving between pages in a LiveView app, you can:

  1. Update the current LiveView
  2. Load a new LiveView

Action

When to Use

How It Works

Update current LiveView

Small changes

Changes data or layout of current page

Load new LiveView

Big changes

Shows a completely new page

To update the current LiveView:

def handle_event("update_page", _, socket) do
  {:noreply, update(socket, :page_data, &Map.put(&1, :new_data, "new value"))}
end

This code changes the page_data when the "update_page" event happens.

To load a new LiveView, use live_redirect as shown earlier.

Choose between updating and loading based on how much the page needs to change. For small changes, update the current LiveView. For big changes, load a new one.

11. Organizing Your Code

11.1 Using Function Components

As your Phoenix LiveView app grows, it's important to keep your code tidy. Function components help with this. They are small, reusable pieces of code that do specific tasks.

To make a function component in Phoenix LiveView, use the defcomponent macro:

defcomponent MyComponent do
  def render(assigns) do
    ~H"""
    <div>
      <h1>Hello, World!</h1>
    </div>
    """
  end
end

You can use this component in your LiveView templates like this:

~H"""
<div>
  <%= MyComponent.render(%{}) %>
</div>
"""

Function components help you:

  • Break big templates into smaller parts
  • Reuse code in different parts of your app

11.2 Working with LiveComponents

LiveComponents are special function components for Phoenix LiveView apps. They can update on their own when your app's data changes. This makes them good for showing real-time updates.

To make a LiveComponent, use the def live_component macro:

def live_component MyLiveComponent do
  def render(assigns) do
    ~H"""
    <div>
      <h1>Hello, World!</h1>
    </div>
    """
  end

  def update(assigns, socket) do
    # Update the component state here
  end
end

You can use this LiveComponent in your templates like this:

~H"""
<div>
  <%= MyLiveComponent.render(%{}) %>
</div>
"""

Here's a table comparing Function Components and LiveComponents:

Feature

Function Components

LiveComponents

Updates

Manual

Automatic

State

No built-in state

Has its own state

Use case

Simple, static parts

Dynamic, data-driven parts

Performance

Lighter weight

Slightly heavier

LiveComponents are useful for making interactive parts of your app that change often.

12. Tips for Better LiveView Apps

12.1 Improving Performance

Here are some ways to make your Phoenix LiveView app run faster:

Tip

How to do it

Make database queries better

  • Use fewer queries
  • Don't load too much data at once
  • Use pagination
  • Use caching

Use caching

Make templates simpler

  • Avoid complex calculations in templates
  • Use template caching
  • Use partials

Use LiveView's built-in tools

  • Use diffing and patching features

12.2 Finding and Fixing Errors

Here's how to spot and fix problems in your Phoenix LiveView app:

Method

What to do

Use browser developer tools

  • Check the console for errors
  • Look at network requests and responses

Use Phoenix debugging tools

  • Try the debugger
  • Use the logger

Test your app well

  • Write tests with ExUnit and Wallaby

Use error tracking tools

  • Try Sentry or Rollbar
  • Watch your app's performance
  • Fix errors quickly

These tips will help you make your LiveView app run better and fix problems faster.

13. Wrapping Up

13.1 Key Points to Remember

Here are the main things to keep in mind as you finish this guide to Phoenix LiveView:

Point

Description

LiveView's purpose

Makes real-time, interactive web apps

Core concepts

mount, handle_event, and render functions

Built-in features

Use diffing and patching for better performance

Best practices

Use caching, pagination, and simple templates

Testing and fixing

Try ExUnit, Wallaby, and the debugger

13.2 Where to Learn More

To keep improving your Phoenix LiveView skills, check out these resources:

Resource

What it offers

Official docs

Full guide with tutorials and examples

Online groups

Connect with other developers, ask questions

Blogs and guides

Learn new tips and methods

Books and classes

Deep dive into LiveView and web development

Open-source projects

Get hands-on experience

These tools will help you build better LiveView apps and solve problems faster.

FAQs

What is the difference between Phoenix and Phoenix LiveView?

Phoenix LiveView

Phoenix and Phoenix LiveView are two tools for building web apps. They work differently:

Feature

Phoenix

Phoenix LiveView

Request handling

Each HTTP request uses a new process

One process handles a WebSocket connection

Page updates

Full page reload needed

Real-time updates without reload

Best for

Traditional web apps

Interactive, real-time apps

Here's how they work in practice:

Phoenix:

  1. User submits a form
  2. Server processes the request
  3. Server updates the database
  4. Server sends a new HTML page to the client
  5. Client's browser loads the new page

LiveView:

  1. User submits a form
  2. Server processes the request
  3. Server updates the database
  4. Server sends only the changed data to the client
  5. Client's page updates without reloading

LiveView is good for making web apps that need to show changes right away, like:

  • Live dashboards
  • Team editing tools
  • Online games

These apps work better with LiveView because it can update parts of the page quickly without loading a whole new page.

Read more, every new tab

Posts like this, on every new tab.

daily.dev curates a feed of articles ranked against what you actually care about. Free forever.

Link copied!