Conflicting documentation on how to handle flash messages

I’m seeing conflicting documentation on how to handle a flash and need guidance on the official way to manage a flash in Phoenix 1.7+ and Phoenix LiveView .20+

PROBLEM: I needed to pull my app menu out of root and into liveview pages. I created a Phoenix.Component for the menu that gets called inside of mostly LiveView pages. Unfortunately, the display of flash messages appear in app.html.eex and live.html.heex. This causes the flash messages to inject themselves between the root header (with logo banner) and my menu. Not desirable!

IN live.html.heex:
<p class="alert alert-info" role="alert" phx-click="lv:clear-flash" phx-value-key="info"><%= live_flash(@flash, :info) %></p>
  <p class="alert alert-danger" role="alert" phx-click="lv:clear-flash" phx-value-key="error"><%= live_flash(@flash, :error) %></p>

IN app.html.eex
<p class="alert alert-info" role="alert"><%= Phoenix.Flash.get(@flash, :info) %></p>
<p class="alert alert-danger" role="alert"><%= Phoenix.Flash.get(@flash, :error) %></p>

I tried removing the code from live.html.heex and inserting into my Phoenix.Component that handles my menu, but of course I get an error that it doesn’t have access to the assign @flash.

So then I read this article on [Updating Flash Messages from PhoenixLiveView](link: Updating flash messages from Phoenix LiveView components · sevenseacat.net) by @sevenseacat . Those instructions (based on LiveView 0.18.18 recommend doing motifications in my_app_web file and inserting a handle_info for :put_flash. But my component is a Phoenix Component, so I’m not sure this will address the issue I’m having in my Phoenix.Component.

Then I looked at my most recent generated code based on upgrading to LiveView .20. I generate a skeleton of my project after doing upgrades to see what is new. In that generated code, it uses a live_flash function inside user_loging_live.ex:

email = live_flash(socket.assigns.flash, :email)

I can see that flash is getting assigned to the socket, but I don’t know how. I believe its being done in the router via :fetch_live_flash. That leads me to look up live_flash function, only to discover that it is deprecated and that we are supposed to use Phoenix.Flash.get/2.

OK … now I’m super confused.

QUESTIONS:

  1. What are the steps I need to follow in order to:
    a) Have access to @flash both in LiveViews and deadviews
    b) Have access to @flash in LiveView components and Phoenix.Components (do I need to follow the instructions from that article above? Will that also address Phoenix.Components)

  2. If I remove flash messages from live.html.heex and app.html.heex then the only role for both of these files is to call @inner_content. I can see from generated code, that root.html.heex and app.html.heex are treated differently in Phoenix 1.7 and LV .20. But I’m too much of a beginner to understand how I move my current code (originally generated on Phoenix 1.5 and Liveview 15) to this new approach.

Does anyone know of a blog post or is there documentation on how to migrate to this new approach? I just don’t know how root.html.heex, app.html.heex piece together. I think it’s all driven by MyAppWeb file but it’s vague how it all comes together.

1 Like

With phoenix 1.7 you should no longer need separate app.html and live.html templates. Flash message API was the last thing missing before but has been normalized for usage in both contexts with phoenix 1.7.

I’d suggest generating a fresh phoenix 1.7 project and trying to align with that if you want to use the latest and greatest boilerplate.

3 Likes

If you want access to @flash in your component, you’d need to pass it as an assign when rendering the component.

My blog post isn’t quite about that - it’s about setting flash messages from components, and having them render in the top-level view.

1 Like