phoenixframework / phoenix_live_view

Rich, real-time user experiences with server-rendered HTML
https://hex.pm/packages/phoenix_live_view
MIT License
6.22k stars 932 forks source link

`phx-remove` Not Respected On Child Elements When Parent Is Removed #3504

Closed probably-not closed 12 hours ago

probably-not commented 12 hours ago

Environment

Actual behavior

phx-remove is meant to allow us to execute JS commands when an element is removed from the DOM. However, when a parent element is removed, phx-remove on its children is not respected and the JS commands are not run.

I've reproduced this with the following Phoenix Playground Example:

Mix.install([
    {:phoenix_live_view, "1.0.0-rc.7"},
    {:phoenix_playground, "~> 0.1.0"}
])

defmodule ExampleComponentLive do
  use Phoenix.LiveComponent
  alias Phoenix.LiveView.JS

  def mount(socket) do
    {:ok, assign(socket, show: false)}
  end

  def update(assigns, socket) do
    socket = assign(socket, assigns)

    send_update_after(
      __MODULE__,
      [id: socket.assigns.id, show: not socket.assigns.show],
      1000
    )

    {:ok, socket}
  end

  def handle_event("show_p", _params, socket) do
    IO.puts("P Is Shown!!!!")
    {:noreply, socket}
  end

  def handle_event("remove_p", _params, socket) do
    IO.puts("P Is Removed!!!!")
    {:noreply, socket}
  end

  def render(%{show: false} = assigns) do
    ~H"""
    <div id={@id}>
    </div>
    """
  end

  def render(%{show: true} = assigns) do
    ~H"""
    <div id={@id}>
      <div id={@id <> "-wrapper"}>
        <p
          id={@id <> "-p"}
          phx-target={@myself}
          phx-mounted={JS.push("show_p")}
          phx-remove={JS.push("remove_p")}
        >
        I'm showing!
        </p>
      </div>
    </div>
    """
  end
end

defmodule ExampleLive do
  use Phoenix.LiveView

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

  def render(assigns) do
    ~H"""
    <.live_component module={ExampleComponentLive} id="1" />
    """
  end
end

PhoenixPlayground.start(live: ExampleLive)

In this example, we receive the show_p event when the <p> is mounted, however, we do not receive the remove_p event when <p> is removed.

Expected behavior

phx-remove should be honored on child elements when their parents are removed.

probably-not commented 12 hours ago

My bad - I was reading old docs - looks like this is well documented 🤦‍♂️