Alert modal appears multiple times in LiveView

I have a LiveView component that allows users to delete a particular record, we use a data confirm to be sure they actually want to delete the record. However, the popup fires 10 or more times before the record is actually submitted.

screencast 2021-09-01 16-43-55

    <%= link "delete", to: "#",
                            class: "btn btn-danger",
                            phx_click: "delete",
                            phx_value_id: msg.id,
                            data_confirm: "Are you sure? (Deleted notifications can not be recovered)" %>

This seems to be an issue similar to the one reported here.
I have found that by moving <%= script_tag src: static_path(@conn, "/js/app.js"), defer: true %> from body into the head as Turbolinks recommends does prevent the modal from popping multiple times. Only, now the record does not get deleted. A console error appears:

phoenix_live_view.js:5 Uncaught TypeError: Cannot read property 'getDescendentByEl' of undefined
    at e.value (phoenix_live_view.js:5)
    at phoenix_live_view.js:5
    at Q (phoenix_live_view.js:5)
    at e.value (phoenix_live_view.js:5)
    at e.value (phoenix_live_view.js:5)
    at phoenix_live_view.js:5
    at Object.debounce (phoenix_live_view.js:5)
    at e.value (phoenix_live_view.js:5)
    at phoenix_live_view.js:5

I’m not sure how to proceed on this.

Try to disable Turbolinks on that specific link by adding data-turbolinks="false" as an attribute.

Also, what’s your initialization ceremony in app.js given that you use Turbolinks?

Adding data-turbolinks="false" makes no difference.

I’m not entirely sure what you mean by “initialization ceremony”, I can provide some info into our setup.
We are requiring turbolinks from a scrip other than /js/app.js

import Turbolinks from "turbolinks";

Turbolinks.start();

app.html.eex:

<%= script_tag src: static_path(@conn, "/js/app.js"), defer: true %>
<%= script_tag src: static_path(@conn, "/js/turbo.js"), async: true %>

/js/app.js is just a collection of custom scripts, libraries, and hooks we import and initialize.

I was referring to the fact that with Turbolinks controlling your navigation, other scripts might need to observe Turbolinks specific events (turbolinks:load) instead of window level events.

1 Like

Ah I see. I think that may have done the trick.

Based on what @snap was doing here I added:

document.addEventListener("turbolinks:load", () => {
  liveSocket.connect();
})

That seems to have fixed the issue.