Adding Toaster message in Phoenix LiveView

AbulAsar S.AbulAsar S.
4 min read

This blog is about adding a Toaster message in the Phoenix LiveView application. We are going to implement this with a combination of Elixir and Javascript. Before, starting to build a toaster let's first answer the most obvious question "What is a Toast?"

What is a Toast?

Toasts are non-interactive, passive, and asynchronous short messages for users. Generally, they are used as an interface feedback pattern for informing the user about the results of an action. This is the most bookish answer about what is a Toast. In the easiest form, it is a popup that provides simple feedback about an operation.

How our toaster should work?

As per definition, a toaster is a popup that provides feedback about an operation. For example, if the user tries to submit a form by clicking the submit button. The user should get feedback after the submission as "Your account is created successfully". In our LiveView application, we want this event(toaster display) should happen after some operation. We are going to call our toaster display logic through pushEvent after that operation. So, our toaster generation logic will be as follows

  • After any operation in Elixir code we will trigger the push_event
  • The push_event will be handled by the handleEvent handler in the javascript Hook
  • This pushEvent handler will ultimately trigger the toaster popup.

Now, that we are ready with our roadmap let's start building 👷

Finding javascript Toaster library

I wanted a vanilla javascript library that should be lightweight and highly supportive in the js community. While doing some research I came across toastify-js. Let's install it in the application. Navigate to the assets directory by running cd assets then run

  npm install toastify-js

Adding the toaster styling

  • We need to import toastify styles in our app.css by adding the following line
    @import "../node_modules/toastify-js/src/toastify.css";
    
  • Next, we will add a javascript hook.

Adding Javascript Hook

After installing toastify we will then add the javascript logic. We will add a mounted callback, which is called and initialized with some initial value as soon as the element on which we are applying it is mounted in the DOM. As we have discussed that our toaster should be called after our elixir code will trigger handle_event. So, we will add our event handler in our mounted callback.

  • Let's add a file in message_toaster.js in assets/js folder.
  • Add a mounted callback with an handleEvent named toast.
import Toastify from 'toastify-js'

MessageToaster = {
  mounted() {
    this.handleEvent('toast', (payload) => {
      Toastify({
        text: payload.message,
        duration: 3000
        }).showToast();        
    })
  }
}
export default MessageToaster
  • We will import Toastify and use it in the handleEvent.
  • In the handleEvent, we have a callback function with a payload param. It will have a custom message which will be used in the Toastify.
  • At last but not least we will include our MessageToaster hook in our LiveSocket. For this, we will open the app.js file and import MessageToaster and include it in our Hooks object, and add the Hooks to our LiveSocket constructor as follows.

      import MessageToaster from "./message_toaster"
      let Hooks = { MessageToaster }
    
      let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}, hooks: Hooks }) 
      # Notice `hooks: Hooks`
    

Registering the Hook

  • To call our Javascript logic i.e hook we’ll add the phx-hook attribute on the root page with value as the hook name i.e MessageToaster. We will add our phx-hook="MessageToaster" on the live.html.heex page.
  • Add the following code

    # lib/project_name_web/templates/layout/live.html.heex
    <div phx-hook="MessageToaster">
         <%= @content %>
    </div>
    

Calling the Toaster

  • As discussed we are going to call our toaster from Elixir code after a certain event. For testing purposes, we are going to add a button in one of our LiveView's HTML code as follows
    # live/user_registration_live.html.heex
    <button phx-click="submit_form">Register User</button>
    
  • Then we will add handle_event for the submit_form
    def handle_event('submit_form', params, socket) do
      # Form submission logic
    end
    
  • In the handle_event after our form submission logic we will make handle_event
      def handle_event("submit_form", params, socket) do
          # Form submission logic
          ....
          ....
          ....
         {:noreply, push_event(socket, "toast", %{message: "Your record has been created successfully"})}
      end
    
  • Final working DEMO is as follows

toaster.gif

I hope you like this blog. If you have any questions then please comment below. Thanks for reading 😊.

References

1
Subscribe to my newsletter

Read articles from AbulAsar S. directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

AbulAsar S.
AbulAsar S.

I am a Software Engineer from Mumbai, India. In love with Functional programming ( precisely Elixir). Love to share the knowledge that I learn while developing things.