DEV Community

Sospeter Mong'are
Sospeter Mong'are

Posted on

1

Building a Simple Counter App with Elixir and Phoenix LiveView

This guide will walk you through creating a simple counter application that demonstrates the basics of Phoenix LiveView.

Step 1: Setting up a new Phoenix project

First, make sure you have Elixir and Phoenix installed. Then, create a new Phoenix project:

# Install Phoenix (if you haven't already)
mix archive.install hex phx_new

# Create a new Phoenix project with LiveView
mix phx.new counter_app --live

# Move into the project directory
cd counter_app

# Set up the database (we won't use it much, but it's required)
mix ecto.setup
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a simple counter LiveView

Create a new file at lib/counter_app_web/live/counter_live.ex:

defmodule CounterAppWeb.CounterLive do
  # Use the LiveView functionality from the web module
  use CounterAppWeb, :live_view

  # mount/3 is called when the LiveView is first rendered
  # It sets up the initial state of the LiveView
  def mount(_params, _session, socket) do
    # Initialize the socket with a count of 0
    # assign/2 is used to set values in the socket's state
    {:ok, assign(socket, count: 0)}
  end

  # handle_event/3 processes events sent from the client
  # This function handles the "increment" event
  def handle_event("increment", _params, socket) do
    # Update the count by adding 1
    # update/3 modifies an existing assign value
    {:noreply, update(socket, :count, &(&1 + 1))}
  end

  # This function handles the "decrement" event
  def handle_event("decrement", _params, socket) do
    # Update the count by subtracting 1
    {:noreply, update(socket, :count, &(&1 - 1))}
  end

  # This function handles the "reset" event
  def handle_event("reset", _params, socket) do
    # Reset the count to 0
    {:noreply, assign(socket, count: 0)}
  end

  # render/1 defines what HTML to display
  # It receives the socket's assigns as its argument
  def render(assigns) do
    ~H"""
    <div class="counter-container">
      <h1>Simple Counter App</h1>

      <!-- Display the current count from assigns -->
      <h2>Count: <%= @count %></h2>

      <div class="buttons">
        <!-- phx-click specifies which event to trigger when the button is clicked -->
        <button phx-click="decrement" class="button">-</button>
        <button phx-click="reset" class="button">Reset</button>
        <button phx-click="increment" class="button">+</button>
      </div>
    </div>
    """
  end
end
Enter fullscreen mode Exit fullscreen mode

Step 3: Add the route for our LiveView

Edit lib/counter_app_web/router.ex to add a route for our counter:

defmodule CounterAppWeb.Router do
  use CounterAppWeb, :router

  # Pipeline definitions (already included when you create a new project)
  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :put_root_layout, html: {CounterAppWeb.Layouts, :root}
    plug :protect_from_forgery
    plug :put_secure_browser_headers
  end

  pipeline :api do
    plug :accepts, ["json"]
  end

  # Browser routes
  scope "/", CounterAppWeb do
    pipe_through :browser

    # Add this line to direct the root path to our CounterLive module
    live "/", CounterLive
  end

  # Other route groups would go here
end
Enter fullscreen mode Exit fullscreen mode

Step 4: Add some basic CSS

Edit assets/css/app.css to add some styling for our counter:

/* Add this to the bottom of the file */

/* Container for the counter application */
.counter-container {
  max-width: 500px;
  margin: 0 auto;
  padding: 20px;
  text-align: center;
  font-family: system-ui, sans-serif;
}

/* Style for the buttons */
.buttons {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 20px;
}

.button {
  padding: 10px 20px;
  font-size: 18px;
  border: none;
  border-radius: 4px;
  background-color: #4a6da7;
  color: white;
  cursor: pointer;
  transition: background-color 0.3s;
}

.button:hover {
  background-color: #2c4a7c;
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Run the application

Start the Phoenix server:

mix phx.server
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:4000 in your browser, and you should see your counter application running!

Understanding the LiveView Flow

  1. When a user visits the page:

    • The mount/3 function is called, initializing the state with count: 0
    • The render/1 function generates the initial HTML
  2. When a user clicks a button:

    • The phx-click attribute tells LiveView which event to trigger
    • LiveView sends this event to the server through the WebSocket connection
    • The corresponding handle_event/3 function is called on the server
    • The state is updated accordingly
    • The render/1 function is called again to update the HTML
    • LiveView sends only the differences (patches) to the browser to update the DOM

This is all handled automatically by LiveView, giving you real-time updates without writing any JavaScript!

Next Steps

To expand this application, you could:

  1. Add more complex state management
  2. Create LiveComponents for reusable UI elements
  3. Implement form validation
  4. Add persistence with Ecto and a database

Congratulations! You've created your first Phoenix LiveView application.

Hot sauce if you're wrong - web dev trivia for staff engineers

Hot sauce if you're wrong · web dev trivia for staff engineers (Chris vs Jeremy, Leet Heat S1.E4)

  • Shipping Fast: Test your knowledge of deployment strategies and techniques
  • Authentication: Prove you know your OAuth from your JWT
  • CSS: Demonstrate your styling expertise under pressure
  • Acronyms: Decode the alphabet soup of web development
  • Accessibility: Show your commitment to building for everyone

Contestants must answer rapid-fire questions across the full stack of modern web development. Get it right, earn points. Get it wrong? The spice level goes up!

Watch Video 🌶️🔥

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs