We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Toggle a modal from a Phoenix LiveView
In the last couple of years I’ve quite often found myself wanting to open a modal from the backend. I totally forgot how I did it last time though, so here is it written down so I’ll remember for all time.
The first thing we’ll to do is add an event listener to our app.js so we can push events to the client from the liveview to open and close the modal.
This will take the id
of a DOM element, the name of an attr
on that element, and then execute the js code we find there. We’ll call it js-exec
and prefix it with the required prefix
// app.js
window.addEventListener("phx:js-exec", ({ detail }) => {
document.querySelectorAll(detail.id).forEach(el => {
liveSocket.execJS(el, el.getAttribute(detail.attr))
})
})
Then we add some data attributes to the modal component. This was generated for us by Phoenix and is located in in core_components.ex
Lets call them data-show-modal
and data-close-modal
and use the helper functions already provided to actually show and hide the modal.
// core_components.ex
def modal(assigns) do
~H"""
<div
id={@id}
phx-mounted={@show && show_modal(@id)}
phx-remove={hide_modal(@id)}
+ data-show-modal={show_modal(@id)}
+ data-close-modal={hide_modal(@id)}
data-cancel={JS.exec(@on_cancel, "phx-remove")}
class="relative z-50 hidden"
>...
Also, in our liveview’s render function, we add a modal that does some cool stuff.
def render(assigns) do
~H"""
<.modal id="my-cool-modal">
... cool stuff goes here
</.modal>
"""
end
Then we push an event from somewhere to execute data-close-modal on our modal.
def handle_event("show_cool_modal", _, socket) do
{:noreply,
socket
|> assign(cool_stuff_to_show: ...)
|> push_event("js-exec", %{
id: "#my-cool-modal",
attr: "data-show-modal"
})}
end
And there we go! We can now open and close modals based on logic in our elixir code. You could for instance throw the push_event into a handle_info function instead, and annoy users based on pubsub messages.
The possibilities truly are endless!