Can't use `Element.remove()` nor `Element.replaceChildren()` in LiveView modal

Whenever I try to use Element.remove() or Element.replaceChildren() on an HTML node that belongs to the subtree of a liveview modal provided by mix.gen.live, the entire modal closes and liveview triggers navigation to the previous page.
Removing phx-remove={hide_modal()} from the liveview modal doesn’t have any effect. Adding phx-update="ignore" doesn’t have any effect either.

This is the default boilerplate code from the liveview modal, in case it is handy:

  def modal(assigns) do
    assigns = assign_new(assigns, :return_to, fn -> nil end)

    ~H"""
    <div id="modal" class="phx-modal fade-in" phx-remove={hide_modal()}>
      <div
        id="modal-content"
        class="phx-modal-content fade-in-scale
         bg-base-100 "
        phx-click-away={JS.dispatch("click", to: "#close")}
        phx-window-keydown={JS.dispatch("click", to: "#close")}
        phx-key="escape"
      >
        <%= if @return_to do %>
          <%= live_patch "✖",
            to: @return_to,
            id: "close",
            class: "phx-modal-close",
            phx_click: hide_modal()
          %>
        <% else %>
          <a id="close" href="#" class="phx-modal-close" phx-click={hide_modal()}>✖</a>
        <% end %>

        <%= render_slot(@inner_block) %>
      </div>
    </div>
    """
  end

  defp hide_modal(js \\ %JS{}) do
    js
    |> JS.hide(to: "#modal", transition: "fade-out")
    |> JS.hide(to: "#modal-content", transition: "fade-out-scale")
  end

Using the same functions inside a shadow root does not present this issue, suggesting that this is a liveview issue.

Additionally, using the functions from the browser console does not present the issue either, example:

document.querySelector("[data-id=label]").remove()

I haven’t used LiveView for a while but isn’t phx-update="ignore" suppose to be set on a container? Meaning element itself isn’t ignored but its children. From the docs

The “ignore” behaviour is frequently used when you need to integrate with another JS library. Note only the element contents are ignored, its attributes can still be updated.

https://hexdocs.pm/phoenix_live_view/dom-patching.html

So you might need a div with phx-update="ignore" that wraps your modal.

yeah I am using .remove() on one of the children inside the node that has phx-update="ignore"

Where are you calling it from? A hook or a script tag?

It would be handy to see the actual code over what the generator emits.

This is not fix for your problem but why do you have phx-remove there? It’s only called when element is removed from DOM. Wouldn’t that call fade-out etc in hide_modal for non existing element when modal element is removed from DOM? Because JS.hide will likely be called on client when element is already removed.

Is it possible you have missed basic HTML issue meaning ids need to be unique for the whole DOM tree. Looking at your code for example you have one element named as close and that’s quite generic. With duplicate ids you can have all sorts of odd behaviors.

As I side note I run into some oddities that you can’t have input element ‘name’ attribute to be id for example because by some odd browser logic there names will be shown as JavaScript field on the element by that name.