ijt
ijt

Reputation: 3825

How can I make an Elixir/Phoenix LiveComponent send a message to itself, not its parent?

I'm writing a ClockComponent to learn about Phoenix LiveComponents. I almost have it, but it's sending the :tick message to its parent. How can I get it to send that message to itself? I wanted to use myself() instead of self() but apparently that's not a thing.

defmodule ClockComponent do
  use Phoenix.LiveComponent

  @impl true
  def mount(socket) do
    if connected?(socket), do: :timer.send_interval(1000, self(), :tick)
    {:ok, assign(socket, date: :calendar.local_time())}
  end

  def handle_info(:tick, socket) do
    {:noreply, assign(socket, date: :calendar.local_time())}
  end

  @impl true
  def render(assigns) do
    ~L"""
    The time is <%= @date |> Timex.to_datetime("America/Denver") |> Timex.format!("{RFC1123}") %>
    """
  end
end

Upvotes: 8

Views: 2749

Answers (2)

sevenseacat
sevenseacat

Reputation: 25029

You can replicate the same behaviour using send_update/3 (or send_update_after/4 for calling after a set amount of time). These will call the update function of the specified module, with the specified arguments.

eg.

defmodule ClockComponent do
  use Phoenix.LiveComponent

  @impl true
  def mount(socket) do
    if connected?(socket), do: tick()
    {:ok, assign(socket, id: "clock", date: :calendar.local_time())}
  end

  @impl true
  def update(%{action: :tick}, socket) do
    tick()
    {:ok, assign(socket, date: :calendar.local_time())}
  end

  @impl true
  def update(assigns, socket) do
    {:ok, assign(socket, assigns)}
  end

  @impl true
  def render(assigns) do
    ~L"""
    The time is <%= @date |> Timex.to_datetime("America/Denver") |> Timex.format!("{RFC1123}") %>
    """
  end

  # This is where the magic happens!
  defp tick() do
    send_update_after(__MODULE__, %{id: "clock", action: :tick}, 1000)
  end
end

Upvotes: 3

Nona
Nona

Reputation: 5462

I don't think you can based on this: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveComponent.html#module-managing-state

Components run inside the LiveView process, but may have their own state and event handling.

I believe both "child component" and parent share the same process.

Upvotes: 6

Related Questions