Fundamentals

Modifying state with events

Read time: 3 minutes

#Welcome to the dynamic world

In a modern front-end framework you don't want a view that shows something and is never modified again. We will learn the first way to modify state in LiveView: events.

We're going to build a simple button that reverses the current user's name. Create an events.exs file with the following code:

Mix.install([
  {:liveview_playground, "~> 0.1.1"}
])

defmodule PageLive do
  use LiveviewPlaygroundWeb, :live_view

  def mount(_params, _session, socket) do
    socket = assign(socket, name: "Lubien")
    {:ok, socket}
  end

  def render(assigns) do
    ~H"""
    <div>
      Hello <%= @name %>

      <input type="button" value="Reverse" >
    </div>
    """
  end
end

LiveviewPlayground.start()

We don't have anything that different to our previous code here except the button. So far just basic HTML. Let's do some magic now. Edit the input and add a handle_event as in the code below:

defmodule PageLive do
  use LiveviewPlaygroundWeb, :live_view

  def mount(_params, _session, socket) do
    socket = assign(socket, name: "Lubien")
    {:ok, socket}
  end

  def render(assigns) do
    ~H"""
    <div>
      Hello <%= @name %>

      <input type="button" value="Reverse" phx-click="reverse" >
    </div>
    """
  end

  def handle_event("reverse", _params, socket) do
    socket = assign(socket, name: String.reverse(socket.assigns.name))
    {:noreply, socket}
  end
end

With this small modification we see the first example of reactivity in Phoenix: phx-click. When clicked, this input generates an event for your LiveView with the name you chose, in this case "reverse". Run the server one more time and see that when you click the button, your name is reverted!

#How do they work?

Let's talk about handle_event/3. This function is a callback that is only necessary if your LiveView has an event. For each event in your HTML code you need a corresponding def handle_event("your_event", _params, socket). The three arguments that this callback receives are, respectively:

Reminder about callbacks!

Callbacks are simply functions that are executed when a certain thing happens.
  • The name of the event you defined.
  • Event parameters (we will explore more in another lesson, at the moment we are just ignoring this argument).
  • The state of the Socket for the current user.

Just like the mount/3 callback you receive the socket so you can modify it however you want. The expected return of the function is {:noreply, socket}.

:ok or :noreply?

You must be wondering why in the callback mount/3 we respond with {:ok, socket} while in handle_event/3 we use {:noreply, socket}.

The mount/3 is just a function that LiveView executes while it's preparing its view, so it follows the Elixir pattern of saying "everything is OK, here's the initial socket".

Now handle_event/3 internally uses an Erlang/Elixir standard called GenServer ("Generic Server") and in the future we will see that we can also return a value for the element that generated the event with {:reply, map(), socket}!

#Recap!

  • By adding phx-click="event_name" to an element you trigger an event name "event_name" when it is clicked.
  • For each event in your HTML you need an equivalent handle_event("event_name", _params, socket) callback.
  • The mount/3 callback returns {:ok, socket} while the handle_event/3 returns {:noreply, socket}.

Feedback

Got any feedback about this page? Let us know!