You can create animated and timed in-app notifications with Phoenix Liveview projects, to give you more flexibility than what flash
messages can offer. This example slides a notice down from the top of the app, then eliminates the notice after 5 seconds. It gracefully handles dynamic content updates. You can enhance the feature to add id
’ or class
values that change how the notification is rendered, or to disappear on a click
event.
The feature works as follows:
- An event requires notification
- In the event handler, change a
socket.assigns.notif_active
parameter value from blank toactive
, change thesocket.assigns.notif_timer
parameter value fromnil
to a newly assignedtimer
reference, and change thenotif_name
andnotif_msg
parameter values in the socket - The page is re-rendered with the new
active
class value, which triggers thecss
to animate the notification - When the timer triggers, handle the
:end_notify
info
event to change thenotif_active
socket param back to blank, causing thecss
to hide the notification - For the use case of new events occurring before the timer expires, call the
Process.cancel_timer/1
method synchronously in the notification event handler before updating socket assigns, so that the new content can be displayed in the notification for the full normal display time period.
This feature requires code in your .css
, .ex
, and .leex
files
.CSS
/*Notifications*/
.notify{
position:absolute;
top:0px;
width:100%;
height:0;
padding: 0;
color:white;
background:rgba(0,105,217,.8);
overflow:hidden;
box-sizing:border-box;
transition:height .2s;
}
#notifyType:before{
display:block;
margin-top:15px;
}
.active{
height:40px;
padding: 5px;
}
.LEEX
Add a div
to your leex
file
<div class="notify <%= @notif_active %>" id="notify"><span id="notifyType" class=""><i>[<%= @notif_name %>]</i> <%= @notif_msg %></span></div>
- The
@notif_active
assign
adds theactive
class to the div to activate the CSS rendering - The
@notif_name
assign
serves as a topic or sender tag in the displayed notification - The
@notif_msg
assign
is the notification body value
.EX
- Assign
notif_timer: nil, notif_name: "", notif_msg: "", notif_active: ""
to your socket on initialization - Activate the notification, cancel any previous timer, and activate a new timer in an event handler. In this case, using a
:chat submitted
event
@impl true
def handle_info({:chat_submitted, my_server, name, chat_msg}, socket) do
notif_timer = socket.assigns.notif_timer
if notif_timer != nil do
Process.cancel_timer(notif_timer)
end
new_notif_timer = Process.send_after(self(), :end_notify, 5000)
{:noreply, assign(socket, server: my_server, notif_timer: new_notif_timer, notif_name: name, notif_msg: chat_msg, notif_active: "active")}
end
- Handle the timer triggered signal to end the notification and mark the timer as ended:
@impl true
def handle_info(:end_notify, socket) do
{:noreply, assign(socket, notif_active: "", notif_timer: nil)}
end