How to redirect from a live view to a controller while keeping socket assigns?

I have a live view where I show a post with comments. Users can post a comment if they’re logged in, and the live view redirects them to the login page otherwise. I’ve generated the authentication stuff with phx_gen_auth, so the login page is a controller which accepts a conn. My redirecting from the live view works fine, but I’d like to be able to include a :redirect_to assign in the conn, so it can return to the post page once a user’s logged in.

Is there a way to set assigns onto the conn when using the Phoenix.LiveView.redirect function?

You could add a param /login?return_to=post_page_url to the login path when redirecting the user to the login page. Then in the login controller you would retrieve the return_to param if present and redirect back to it once logged in. To take this even further, also add a #comment hash (/login?return_to=post_page_url#comment) so that it will scroll the page to the post comment editor (this DOM container needs to have id=comment). Makes sense?

2 Likes

Yeah, this makes sense and it’ll work in this case. It’d be kind of a shame to not have some way of passing socket->conn assigns: What if I have a changeset that I need to pass from socket to conn? I wouldn’t be able to include that in the params (nicely).

I think that this thread LiveView: Merge assigns from conn to socket might shed some light on your situation.
If I understood correctly what you’re looking for there isn’t a straightforward way of doing it but a couple of alternatives are presented on the thread above.

1 Like

This is simply not possible. The liveview process is gone by the time the http route is hit. The only way to pass information forward is via the client (url is one option within that).

1 Like

You can either do another login screen with live view, or embed the return path into the query string of the login screen URL, so the login screen knows where to redirect.

1 Like

It’s a shame we can’t insert into the session from the liveview, as it’d be a nice way to do it without using the url.

There are ways to write into the session even from a LiveView (via JS), but I see only cons to doing so in this scenario. With the session you would also have to clean after yourself. Otherwise, when you intend to do a clean redirect just to the login page, you’ll find out you get redirected to whatever it was last written to the session. I look at the session as a very limited, expensive operation, that I only touch as a last resort.

With the url approach, it’s straight-forward and cost-free. When you construct the login path from any liveview, you can make use of the uri param in the handle_params callback as the return_to value. This way, unless you want to further personalize it (like my idea with the hash thing), it works in a general case pretty good.

1 Like

You can use an agent or ETS to temporarily cache the data, and pop from the cache when used

That however brings with it all the problems of a cache:

How long need things to be stored? How to deal with requests coming in after things were deleted? How to handle that in a multi node setup? How do deal with network issues (e.g. the client loosing connection before receiving a response, then tries again later, but the server already deleted stuff after the first request was served)?

Agreed, there are many drawbacks to a caching approach, but there aren’t much other options for sharing private data from socket to conn. Imo it’ll be great if liveview can simply update the session. Current methods feel like hacks, because of having to trigger an ajax request and it being not private

With server side session stores this would be doable. But for the cookie based session store there simply is no way to do that besides with hacks.