JS.show in handle_event instead of phx-click with JS.show

I have an element defined like

<img class="sdicon" phx-click={JS.show(to: "#click-target", transition: "fade-in-scale")} src={~p"/images/icons/myicon.png"}>

That works fine but I’d like to define it like:

<img class="sdicon" phx-click="icon-clicked" phx-value-target="#click-target" src={~p"/images/icons/myicon.png"}>

and have an event handler

	def handle_event("icon-clicked", %{"target" => target} = unsigned_params, socket) do
		# here some important stuff that needs to be done upfrong
		# then an equivalent of JS.show(to: target, transition: "fade-in-scale")

		{:noreply, socket}
	end

that does some additional “important stuff” before the JS.show

Any suggestions how to do this “properly”? I know I can push custom event combined with window listener unless there are better options. But even then, how do I do the JS.show equivalent in the listener?

Hi!

Do you really want to wait until the server event is handled before changing the page?

If so, you have a few options:

But maybe you’d be better off doing an optimistic UI change, see José Valim explain in https://youtu.be/fCdi7SEPrTs?si=iyxZM8FdE7clKYKI.

Also at Syncing changes and optimistic UIs in the official docs.

1 Like

I think so. That may sound old-skoolish but I kind of prefer to show the UI element once I know the backend operations related to this element being shown finished successfully or I trigger an alert instead, etc.

Even if I wanted to do “optimistic” I still need two operations, so I guess I’d need to trigger a frontend function, which would then push an event to the server. I’ll have a closer look at the videos/docs you mentioned but I am somewhat sceptical whether this is optimal for the case at hand. I’ll check. Maybe I am wrong on that.

That’s the option I considered too. Would require rewriting some parts but if I don’t find anything better I might go for that.

Right, that’s the first that comes to mind but I am unsure how to do the exact equivalent of JS.show(to: "#click-target", transition: "fade-in-scale", possibly other options too. I know I can modify classes and attributes myself but if I wanted to utilise the already loaded liveview functions then how do I do that? Other than digging out the JS implementation of them, that is.

Isn’t that basically the same as having JS.show in the attribute?

I would just store the state on the server, then, as this is what LiveView is good at. If the Important Stuff changes assigns in some way, you can just inspect that to show or hide the element, but hard to say without a concrete example. To get the transition, use JS.transition with phx-mount.

<div
  :if={@condition_to_show}
  phx-mounted={JS.transition("fade-in-scale")}
>
  Oh, hi!
</div>

You can also use push_event and liveSocket.execJS, for example: