How to inject a Phoenix Component dynamically into a template whenever a button is pressed, and allow that action to be performed an indeterminate number of times?

defmodule HelloComponent do
  use Phoenix.Component

  def greet(assigns) do
    ~H"""
    <p>Hello</p>
    """
  end
end
defmodule MyAppWeb.HelloLive do
  use MyAppWeb, :live_view
  import HelloComponent

  def mount(_params, _session, socket) do
    {:ok, socket}
  end

  def handle_event("hello", _, socket) do
    IO.puts("HelloComponent injected")
    {:noreply, socket}
  end

  def render(assigns) do
   ~H"""
      <button phx-click="hello">+</button>
      <%# Inject another HelloComponent here each time button is pressed%>
    """
  end
end

After pressing the button 3 times, the webpage would look something like:

+
Hello
Hello
Hello

How can I accomplish this? I am not sure if the handle_event is the correct way to go about it.

You need to keep track some state, and when the state change, the ui changes as well.

There are probably many ways to do this, but a simple one would be to use some counts, and render this count as a hello component.

defmodule MyAppWeb.HelloLive do
  use MyAppWeb, :live_view
  import HelloComponent

  def mount(_params, _session, socket) do
    {:ok, socket |> assign(:count, 0) }
  end

  def handle_event("hello", _, socket) do
    IO.puts("HelloComponent injected")
    {:noreply, socket |> assign(:count, socket.assigns.count + 1)}
  end

  def render(assigns) do
   ~H"""
      <button phx-click="hello">+</button>
     <%= for _ <- 0..@count do %>
      <HelloComponent.hello />
     <% end %>
    """
  end
end
2 Likes