When writting LiveView applications most of my DB actions/calls
that changed rows were doing INSERT/UPDATE/DELETE operation
then broadcast call on PubSub so everyone connected to given view,
interested in changes to given thing can get updated version,
so everyone can see most recent version of the thing.
This means that whichever piece of code does change in DB also listens to changes in it.
Because of that, we can either deal with the new result after we get it or ignore it and
wait for a message from PubSub.
The solution for this problem is pretty simple.
Let's start by creating module MyAppWeb.Flash.
defmodule MyAppWeb.Flash do
alias Phoenix.LiveView
def result_flash(result, socket) do
case result do
:ok -> LiveView.put_flash(socket, :info, "Success!")
{:ok, _} -> LiveView.put_flash(socket, :info, "Success!")
{:error, reason} -> LiveView.put_flash(socket, :error, reason)
end
end
end
With this, when we have a schema operation returned, we can show a success flash or error flash
with just simple pipes and go on with our lives, waiting for PubSub message.
For example:
defmodule MyAppWeb.Live.SomeView do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
if connected?(socket) do
MyApp.SomeSchema.subscribe()
end
{:ok, assign(socket, values: MyApp.SomeSchema.all())}
end
def handle_event("new", form, socket) do
{:noreply, form |> MyApp.SomeSchema.new() |> MyAppWeb.Flash.result_flash(socket)}
end
def handle_info({MyApp.SomeSchema, value}, socket) do
{:noreply, assign(socket, values: [value | socket.assigns.values])}
end
end
You can add it into your MyAppWeb module in the live_view part
of the __using__ macro to automatically import this function.
defmodule MyAppWeb do
def live_view do
quote do
# ...other code...
import MyAppWeb.Flash, only: [result_flash: 2]
unquote(html_helpers())
end
end
end
This way all you will need in LiveViews will be |> result_flash(socket).
This is not an extremely complicated change, but a convenience that is nice to have. You can extend it with knowledge and functionalities from [Put flash from anywhere]({{< ref "posts/put_flash_from_anywhere" >}}) or [Subscribe from live components]({{< ref "posts/live_component_subscribe" >}}) to make it work in all places along the application.