Erlang/OTP 22 [erts-10.6.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]Elixir 1.10.1 (compiled with Erlang/OTP 21)* phoenix 1.4.13 (Hex package) (mix)phoenix_live_view 0.7.1 (Hex package) (mix)v13.7.06.13.6Linux 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/LinuxMozilla Firefox 73.0.1Chromium 79.0.3945.130 built on Debian 10.2, running on Debian 10.3live_render/3 return from a controllerlive_redirect/2 templates in the user facing html are no longer clickable, throwing the following JavaScript console error when clicked:TypeError: this.main is null app.js line 119 > eval:568:19
value webpack:///../deps/phoenix_live_view/priv/static/phoenix_live_view.js?:568
value webpack:///../deps/phoenix_live_view/priv/static/phoenix_live_view.js?:861
value webpack:///../deps/phoenix_live_view/priv/static/phoenix_live_view.js?:836
// phoenix_live_view.js; lines 562-581
{
key: "replaceMain",
value: function (e, t) {
var n = this,
i = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : null,
r = arguments.length > 3 && void 0 !== arguments[3] ? arguments[3] : this.setPendingLink(e),
o = this.main.el, // ERROR here; line 568:19
a = this.main.id;
this.destroyAllViews(), this.main.showLoader(this.loaderTimeout), U.fetchPage(e, function (c, u) {
if (200 !== c) return U.redirect(e);
var s = document.createElement("template");
s.innerHTML = u;
var l = s.content.childNodes[0];
if (!l || !n.isPhxView(l)) return U.redirect(e);
n.joinView(l, null, e, t, function (e) {
n.commitPendingLink(r) ? (n.destroyViewById(a), o.replaceWith(e.el), n.main = e, n.main.showLoader(), i && i()) : e.destroy();
});
});
}
}
/auth/signinThe live_redirect/2 links should render new pages when clicked. No javascript error should be thrown.
live_redirect links are only supported via LiveViews rendered from the router via live definitions. I will try to improve the error in such cases, but this is not expected to work. Thanks!
Would it be possible to have the live_redirect links fallback to normal anchor tags when an exception occurs? This is the behaviour when users have JavaScript disabled.
live_redirect links indeed fallback to regular links when JS is disabled :)
We will not allow live_redirects from DeadViews because live navigation and valid URLs cannot be guaranteed. You should use live routes and avoid rendering LiveViews from the controller
live_redirect links indeed fallback to regular links when JS is disabled :)
This surprised me when I discovered it! I am very thankful for the hard work and careful design. :smile:
We will not allow live_redirects from DeadViews because live navigation and valid URLs cannot be guaranteed. You should use
liveroutes and avoid rendering LiveViews from the controller
I have difficulty understanding how the URL is no longer guaranteed when a no JS fallback exists.
Without this fallback, I will need to rethink how I manage live view -> session mutations in my app.
Can you provide some insight into my thought process? (based off of https://github.com/phoenixframework/phoenix_live_view/issues/501#issuecomment-558286950)
redirect/2 to a non live route for checking DB pending session updatesput_session/3)redirect/2 back to the LiveViewAm I missing something obvious? This seems like a cumbersome approach.
Is there a better way without incurring 2 DB operations (insert, delete) for modifying browser session state?
We can support the regular link fallback, but I am saying there is no good reason to use live_render from a controller or regular view other than slotting LV into an existing app. You lose features, usually have redundant data access, code paths, etc. If you have a controller which does a put_session, it can redirect back to live route instead of rendering the LV.
The reason I was using live_render/3 was to pass a changeset into the session (through opts).
The redirect approach does not have this parameter, and the changeset can be too large to use conn assign/3.
Edit: clarifying problem (writing this on mobile)
Back at my laptop. Here is a more concrete example of motivation for the live_render/3 fallback.
I want to send the changeset from the post controller to the liveview.
It is unclear how to do this using Phoenix.Controller redirect/2.
# defmodule MyAppWeb.Router
# stub router code snippet
scope "/auth" do
live "/signin", AuthLive.SignIn, :new
post "/signin", AuthController, :post_signin
end
# defmodule MyAppWeb.AuthController
# stub post controller function
def post_signin(conn, %{"session" => session}) do
changeset = %User{}
|> User.changeset(session)
|> Map.put(:action, :insert)
conn
|> put_flash(:error, "Invalid username or password")
# current approach, but breaks links
# |> live_render(MyAppWeb.AuthLive.SignIn, session: %{"changeset" => changeset})
# values from assign cannot retrieved within liveview socket
|> assign(:changeset, changeset)
# Plug.Conn.CookieOverflowError:
# cookie named "_myapp_key" exceeds maximum size of 4096 bytes
|> put_session(:changeset, changeset)
# Links work, but how to pass the changeset?
|> redirect(to: Routes.auth_sign_in_path(conn, :new))
end
# MyAppWeb.AuthLive.SignIn
# stub live view mount function, how to retrieve the changeset?
def mount(_params, %{"changeset" => changeset} = session, socket) do
{:ok, socket
|> assign(changeset: changeset)
end
Most helpful comment
We will not allow live_redirects from DeadViews because live navigation and valid URLs cannot be guaranteed. You should use
liveroutes and avoid rendering LiveViews from the controller