It does. Just keep in mind that JS.patch(query: merge: lorem: "ipsum", dolor: "sit") is not valid Elixir syntax. You’d need to write JS.patch(query: [merge: [lorem: "ipsum", dolor: "sit"]]).
side note: I explored navigation guards for LiveView in the past, but the browser APIs are very lacking at the moment and there’s no good way to actually cancel a navigation caused by pressing the back/forward buttons. It needs a lot of manual state bookkeeping, so I abandoned that even though I really wanted to have that feature. The most popular use case for such guards would be to prevent navigation when there are unsaved changes, but one more catch there is that you cannot prevent a server initiated navigation on the client, because the LiveView process simply shuts down when you do `push_navigate`. So even if there were navigation guards, you’d still need to also be careful about server initiated navigations.
There might be cases where it’s brittle, but for me this is mostly about filters in tables where you’re only concerned about a single or maybe set of query parameters that are unrelated to any other filters you have.
With you example, whenever @uri_switch changes, all js_patch commands will be re-sent. If you have a lot of buttons / links on a page (like a country selector with hundreds elements that should all change the URL) this can get expensive fast.
This is pretty good and it actually benefits from something I wasn’t fully aware of: when you `push_patch` from a handle_event, the patch does not incur an additional client-server roundtrip. The LiveView just directly calls handle_params and sends two messages over the websocket: the new URL that is patched to for updating the client-side URL and the handle_event diff response.
Correct. That’s actually the reason I started with the client-side URL patching in the first place. Previously, I built links on the server, which looked something like this:
~H"""
<.link patch={~p"/my-page?#{Map.put(@params, "country", "US")}"}>United States</.link>
"""
which has the exact same issue that all the links relying on the current @params get re-sent. The big benefit of this approach (and why I still like it for use cases where you don’t render thousands of links on the page) is that you can command/alt click the link and also right click to copy the URL to send someone else, etc.
That doesn’t work with any of the client side patch or handle_event based approaches.
Note that if you do you push_navigate, the optimization I mentioned earlier does not apply. In that case, you need two round trips to perform the navigation if you use the handle_event based approach. Initiating the live navigation from the client only needs one round trip as the client directly joins the new LiveView channel. Most of the time you’d probably use patch though.
Quoting myself:
you can command/alt click the button/link and also right click to copy the URL to send someone else, etc.
Technically, you can of course make this work with more JavaScript. You hook into both the LiveView DOM patching (there’s onPatchEnd) and the popstate event and then compute the correct href value based on the current URL and set it using liveSocket.js().setAttribute. But then, this may best be explored in a separate library first.






















