But now, I have a requirement that I call that url for the user from the server side after a form validation, something like this:
def handle_event("submit_export", %{"form" => form}, socket) do
# Handles form and generates a params variable
...
{:noreply, redirect(socket, external: ~p"/csv/exporter?#{@params}")}
end
This will call the CSV route and the user will get the CSV downloaded, but, it will also disconnect the page LV websocket and never reconnect it again since it assumes that the page will be redirected for some other page (which it doesn’t since this redirect is not to a page but to the CSV file directly).
I also tried using push_navigate without success.
The only way I found that worked was a workaround by having a custom hook that I send a push_event to it and the hook will call the url directly from the client instead of doing it from the server side.
So, is there some way to achieve that directly from server side (maybe some way to tell that the redirect needs to be in another tab/window?)?
I couldn’t find his post, but right now here is my solution (which I’m not happy with tbh, I feel that something like this should be supported out-of-box in LV).
In app.js:
// Open url in new tab/window
window.addEventListener(
"phx:open-url-in-new-window",
({ detail: {url} }) => {
window.open(url, "_blank", "noopener, noreferrer")
}
)
And then I use it like this in my handle_event call:
def handle_event("submit_export", %{"form" => form}, socket) do
# Handles form and generates a params variable
...
{:noreply, JSExtra.open_url_in_new_window(socket, ~p"/csv/exporter?#{@params}")}
end
I don’t believe you need this kind of indirection. This could be entirely client side without having to go back to your liveview. There are JS commands for this kind of stuff Phoenix.LiveView.JS — Phoenix LiveView v1.0.17 but I’m afraid it wont open a new tab in the background.
You could properly get away with using a traditional link
Not sure if I understand your suggestion, the final url is only generated during the “submit” event in my form, hence why I want to do the redirect from the server side.
I’d create an event listener combined with push_event, which creates a temp link with download attribute on the body and clicks it. That way you get all the benefits of no new tab, but also the LV page not stopped. Maybe there could be a JS.push_download(url), but it’s not too hard to build that with existing primitives.