Building Realtime LiveView App using Phoenix PubSub

In my previous blog on the Note-taking app, we missed harnessing the most important feature of Phoenix LiveView i.e real-time update. What does that mean? It means to do an update in your application screen without explicitly refreshing your application. For example, in a chat app, you don't have to explicitly refresh your screen to see the change in the screen. In our previous version of the Notetaking app when we add the note in the screen and if there is a browser screen opened parallel with the existing one then that new note won't be reflected, you have to refresh the browser to see the result. In this blog, we are going to add this new feature to our previous blog code.
Refer to the gif below for the complete real-time update version of the app that we are going to make.

How PubSub works? 🤔
Phoenix PubSub is an API that is responsible for doing live updates in the app. The documentation itself says it's a Realtime Publisher/Subscriber service. In application, our LiveView(module) process subscribes to a particular channel(s). When a message is published on a topic, the message is broadcast. Similarly, when a message is published from a topic, the message is broadcast to all the subscribers of that topic. When the broadcast message is received to the subscribed Process their state is updated which ultimately re-renders the view. Below diagram will give you an idea about subscribers and
Subscriber

Publisher

Adding the Subscriber
- We've understood the concept of the subscriber. It will be a function that will be called by the LiveView module.
- The
Phoenix.PubSubmodule has asubscribefunction that takes 2 parameters.- The PubSub instance of our app, in our case it is
NoteApp.PubSub - The name of the channel/topic, in our case it is "notes"
- The PubSub instance of our app, in our case it is
- Question arises where do we place this function. Ideally, it should be placed in the context API layer but we haven't created any context API layer. So, we will create a new module
lib/note_app/notes/note.exand the following code.defmodule NoteApp.Notes.Note do def subscribe() do Phoenix.PubSub.subscribe(NoteApp.PubSub, "notes") end end
Publishing/Broadcasting the message
- We know that PubSub has a
subscribefunction, likewise, it also has abroadcastfunction in it. - We have to call this function to
publish/broadcastthe message. - As per our requirement we want to publish the message(note) as soon as we create the note.
- So our logic will reside in our
create_notecallback just after creating the note. - We need to pass the message as a tuple with the first field as the
message name(as an atom) in our case it will be:create_noteand the other field is thenotecreated.
lib/note_app/notes/note_server.ex
def handle_cast({:create_note, note}, notes) do
updated_note = add_id(notes, note)
updates_notes = [updated_note | notes]
message = {:note_created, updated_note}
#broadcast logic -start
Phoenix.PubSub.broadcast(
NoteApp.PubSub,
"notes",
message
)
#broadcast logic -end
{:noreply, updates_notes}
end
- The
broadcastfunction takes 3 parameters.- The PubSub instance of our app, in our case it is
NoteApp.PubSub - The name of the channel/topic, in our case it is "notes"
- The
messagewe want tobroadcast.
- The PubSub instance of our app, in our case it is
Subscribing to the Topic/Channel
- Any LiveView process which needs to be updated has to subscribe to the topic/channel.
- We have already created a
notestopic. - Our
NotesListsLiveView needs to subscribe to this topic/channel. - This is achieved very easily, we just need to add call the
subscribefunction in themountcallback. - But there is a caveat, we can only call the
subscribefunction when our LiveView is connected tosocket. Also, we need to alias theNotemodule to uselib/note_app_web/live/notes_index_live.exdefmodule NoteAppWeb.NotesIndexLive do alias NoteApp.Notes.Note def mount(_params, _session, socket) do if connected?(socket), do: Note.subscribe() ..... ..... ..... end end - We know LiveView is nothing but a GenServer process, so when the publisher broadcasts the message our LiveView process needs to handle that message. We will achieve that with the
handle_infocallback in ourNotesListLiveView module. Add the following function in the module.
lib/note_app_web/live/notes_index_live.ex
defmodule NoteAppWeb.NotesIndexLive do
........
........
........
def handle_info({:note_created, note}, socket) do
socket = update(socket, :notes, fn notes -> [note | notes] end)
{:noreply, socket}
end
end
- We pattern match the
broadcastmessage and retrieve thenoteand update thenoteslist in the socket with the latest message.
I hope you like this easy implementation of using Phoenix PubSub for achieving live updates. If you have any questions then please comment below.




