I see how I can hide a modal with phx-remove={hide_modal()}.
But is it possible to trigger the show and hide of a modal with Phoenix.LiveView.JS from the server or would that be the wrong tool for that? Actually I’d like to trigger the show of the modal on the server and use the client to hide it.
LiveView.JS is intended to avoid the round-trip to the server and execute commands one the client side. So you could use it to hide elements on the client, but triggering stuff from the server-side is still done using the assigns on the socket.
I am sorry to reopen a solved topic, but I am struggling with a similar problem.
I am using the core component modal.
I just want to hide the modal from the server, and I can’t figure out how.
How did you manage to solve to do that (in your case it is open, but still…)?
Why not just flip an assign e.g. @visible to trigger a re-render that removes the modal?
<.modal :if={@visible} id="my-modal" show>
That’s how the default mix phx.gen.live templates control whether to show or hide the modal form components from the server based on LiveNavigation events that update the @live_action assign.
<.modal :if={@live_action in [:new, :edit]} id="user-modal" show on_cancel={JS.patch(~p"/users")}>
Ok, but how can I switch it back to let the modal be opened multiple times.
Right now I am opening the modal with phx-click={show_modal("user-create-modal")}
You could include a JS.push in your show_modal function to update the server and assign.
Composing JS.push with other JS commands
If we’re using JS.push to send our event, we can orchestrate client-side transition effects along with our push, simply by composing it with other LiveView JS commands!
This applies a transition named shake to the div with id content, totally client-side, at the same time the event is being processed and the content assign is changed.
It is common for a LiveView to have multiple states and multiple URLs. For example, you can have a single LiveView that lists all articles on your web app. For each article there is an “Edit” button which, when pressed, opens up a modal on the same page to edit the article. It is a best practice to use live navigation in those cases, so when you click edit, the URL changes to “/articles/1/edit”, even though you are still within the same LiveView. Similarly, you may also want to show a “New” button, which opens up the modal to create new entries, and you want this to be reflected in the URL as “/articles/new”.
In order to make it easier to recognize the current “action” your LiveView is on, you can pass the action option when defining LiveViews too:
live "/articles", ArticleLive.Index, :index
live "/articles/new", ArticleLive.Index, :new
live "/articles/:id/edit", ArticleLive.Index, :edit
…
The current action will always be available inside the LiveView as the @live_action assign, that can be used to render a LiveComponent:
<%= if @live_action == :new do %>
<.live_component module={MyAppWeb.ArticleLive.FormComponent} id="form" />
<% end %>