Trigger the show of a modal with Phoenix.LiveView.JS

I walk through the docs of Phoenix.LiveView.JS in LiveView 0.17.1 Phoenix.LiveView.JS — Phoenix LiveView v0.17.1

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.

Maybe take a look at ElixirConf 2021 - Chris McCord - The Future of Full-stack
At about 33min the JS Commands are explained and demoed.

6 Likes

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…)?

1 Like

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")}

Should I change it to an handle_event?

Thank you

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!

Let’s try with the JS.transition command:

<button phx-click={
    JS.push("clicked", value: %{val1: "At", val2: "the", val3: "disco!"})
    |> JS.transition("shake", to: "#content")
  }
>
  Panic! 
</button>

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.

source: Pushing Events: with and without JS.push · The Phoenix Files

1 Like

Thanks, that give me the idea how its works. But how does @live_action assign on LiveView when we click :new or :edit button?

Welcome to the forum!

@live_action is a special assign that can be set from the router when defining the LiveView route e.g. live /articles/new, ArticleLive.Index, :new.

Actions and live navigation

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 %>

source: Phoenix.LiveView.Router — Phoenix LiveView v0.20.2

Wow, Thanks. Thats answered my question

Found Triggering JS from the server in LiveView: showing a spinner · The Phoenix Files that explains how to trigger client side behaviour from server. Used the approach to open up a modal from server side.

1 Like