Hi all, I’m having trouble with showing my flash messages when using a mix of conventional phoenix controllers (to be able to set cookies) and liveviews. This is specifically happens when I am using the user log in/sign up workflow (which was pretty heavily tweaked from the phx.gen.auth code). The desired process looks like this:
/register (live view for validations) → POST to controller at /user/register, set http only cookie with session token → redirect to /home (liveview)
I’d like the flash messages to show on the /home liveview, but they aren’t.
Relevant code:
register_controller.ex
:
defmodule MyAppWeb.RegisterController do
use MyAppWeb, :controller
...
def register(conn, %{"user" => user_params}) do
with {:ok, %User{} = user} <- Accounts.register_user(user_params) do
Accounts.send_user_registration_email(user)
token = Accounts.generate_user_token(user, "session")
user_return_to = get_session(conn, :user_return_to)
conn
|> renew_session()
|> put_session(:user_token, token)
|> put_session(:live_socket_id, "users_sessions:#{token}")
|> put_flash(:success, "Welcome to MyApp, #{user.first_name}!")
|> maybe_write_remember_me_cookie(token, user_params)
|> redirect(to: user_return_to || signed_in_path(conn))
end
end
end
app.html.eex
:
<main role="main">
<div class="absolute flex flex-row my-3 w-screen justify-center items-center">
<% success_msg = get_flash(@conn, :success) %>
<% success_visibility = unless success_msg, do: "hidden", else: "" %>
<div class="flex flex-row items-center rounded shadow border-2 border-green-300 mx-10 my-2 bg-green-200 <%= success_visibility %>" role="alert" phx-click="lv:clear-conn" phx-value-key="success">
<p class="m-2 flex-grow text-green-700"><%= success_msg %></p>
<svg class="w-5 h-5 mr-2" fill="#047857" role="button" viewBox="0 0 20 20"> <path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
</div>
</div>
<div class="absolute flex flex-row my-3 w-screen justify-center items-center">
<% info_msg = get_flash(@conn, :info) %>
<% info_visibility = unless info_msg, do: "hidden", else: "" %>
<div class="flex flex-row items-center rounded shadow border-2 border-blue-300 mx-10 my-2 bg-blue-200 <%= info_visibility %>" role="alert" phx-click="lv:clear-flash" phx-value-key="info">
<p class="m-2 flex-grow text-blue-700"><%= info_msg %></p>
<svg class="w-5 h-5 mr-2" fill="#1D4ED8" role="button" viewBox="0 0 20 20"> <path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
</div>
</div>
<div class="absolute flex flex-row my-3 w-screen justify-center items-center">
<% error_msg = get_flash(@conn, :error) %>
<% error_visibility = unless error_msg, do: "hidden", else: "" %>
<div class="flex flex-row items-center rounded shadow border-2 border-red-300 mx-10 my-2 bg-red-200 <%= error_visibility %>" role="alert" phx-click="lv:clear-flash" phx-value-key="error">
<p class="m-2 flex-grow text-red-700"> <%= error_msg %> </p>
<svg class="w-5 h-5 mr-2" fill="#B91C1C" role="button" viewBox="0 0 20 20"> <path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
</div>
</div>
<%= @inner_content %>
</main>
live.html.leex
:
<main role="main" class="bg-gray-50 h-screen overflow-scroll">
<div class="absolute flex flex-row my-3 w-screen justify-center items-center">
<% success_msg = live_flash(@flash, :success) %>
<% success_visibility = unless success_msg, do: "hidden", else: "" %>
<div class="flex flex-row items-center rounded shadow border-2 border-green-300 mx-10 my-2 bg-green-200 <%= success_visibility %>" role="alert" phx-click="lv:clear-flash" phx-value-key="success">
<p class="m-2 flex-grow text-green-700"><%= success_msg %></p>
<svg class="w-5 h-5 mr-2" fill="#047857" role="button" viewBox="0 0 20 20"> <path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
</div>
</div>
<div class="absolute flex flex-row my-3 w-screen justify-center items-center">
<% info_msg = live_flash(@flash, :info) %>
<% info_visibility = unless info_msg, do: "hidden", else: "" %>
<div class="flex flex-row items-center rounded shadow border-2 border-blue-300 mx-10 my-2 bg-blue-200 <%= info_visibility %>" role="alert" phx-click="lv:clear-flash" phx-value-key="info">
<p class="m-2 flex-grow text-blue-700"><%= info_msg %></p>
<svg class="w-5 h-5 mr-2" fill="#1D4ED8" role="button" viewBox="0 0 20 20"> <path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
</div>
</div>
<div class="absolute flex flex-row my-3 w-screen justify-center items-center">
<% error_msg = live_flash(@flash, :error) %>
<% error_visibility = unless error_msg, do: "hidden", else: "" %>
<div class="flex flex-row items-center rounded shadow border-2 border-red-300 mx-10 my-2 bg-red-200 <%= error_visibility %>" role="alert" phx-click="lv:clear-flash" phx-value-key="error">
<p class="m-2 flex-grow text-red-700"><%= error_msg %></p>
<svg class="w-5 h-5 mr-2" fill="#B91C1C" role="button" viewBox="0 0 20 20"> <path d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" fill-rule="evenodd"></path></svg>
</div>
</div>
<%= @inner_content %>
</main>
Oh, and note: the only time the flash messages do work and are rendered are in the incorrect user/pass login flow:
/login (liveview) → POST to /user/login → live_render(conn, MyAppWeb.LoginLive)
It still does not show the flash message when redirected to the /home liveview after logging in.
login_controller.ex
:
defmodule MyAppWeb.LoginController do
use MyAppWeb, :controller
import Phoenix.LiveView.Controller, only: [live_render: 3]
def login(conn, %{"user" => %{"email" => email, "password" => password} = user_params}) do
with %User{} = user <- Accounts.get_user_by_email_and_password(email, password) do
Accounts.send_user_registration_email(user)
token = Accounts.generate_user_token(user, "session")
user_return_to = get_session(conn, :user_return_to)
conn
|> renew_session()
|> put_session(:user_token, token)
|> put_session(:live_socket_id, "users_sessions:#{token}")
|> put_flash(:success, "Welcome back, #{user.first_name}!")
|> maybe_write_remember_me_cookie(token, user_params)
|> redirect(to: user_return_to || signed_in_path(conn))
else
nil ->
conn
|> put_flash(:error, "Email/password combination incorrect")
|> live_render(StreetHeroWeb.LoginLive, session: %{"email" => email})
end
end
end
What should I be doing differently to get the flash messages appear? And I guess am I even using redirect
correctly? Should this instead be live_redirect
? Thanks!