Automatically clearing flash messages in Phoenix LiveView

Hey, I created a hook to automatically clear flash messages after 5 seconds, in case it’s of anyone’s interest :slight_smile:

Here’s the code

// app.js
let liveSocket = new LiveSocket("/live", Socket, {
  // ...
  hooks: {
    AutoClearFlash: {
      mounted() {
        let ignoredIDs = ["client-error", "server-error"];
        if (ignoredIDs.includes(this.el.id)) return;

        let hideElementAfter = 5000; // ms
        let clearFlashAfter = hideElementAfter + 500; // ms

        // first hide the element
        setTimeout(() => {
          this.el.style.opacity = 0;
        }, hideElementAfter);

        // then clear the flash
        setTimeout(() => {
          this.pushEvent("lv:clear-flash");
        }, clearFlashAfter);
      },
    },
  },
});

I also created a post on dev.to with more details: Automatically clearing flash messages in Phoenix LiveView - DEV Community

12 Likes

Simple and works well. Thanks!

1 Like

It’s a nice solution! However, while testing it by triggering an event that causes a flash notification multiple times within the preconfigured 5 seconds, I consistently encountered the following error:

view.js:1521 Uncaught (in promise) Error: unable to push hook event. LiveView not connected
    at _View.pushHookEvent (view.js:1521:9)
    at _ViewHook.pushEvent (view_hook.ts:388:35)
    at hooks.js:19:12
pushHookEvent @ view.js:1521
pushEvent @ view_hook.ts:388
(anonymous) @ hooks.js:19
setTimeout
mounted @ hooks.js:17

So, I slightly modified it, probably not perfectly, by wrapping this.pushEvent in the following if clause:

setTimeout(() => {
  if (this.view && this.view.isConnected()) {
    this.pushEvent("lv:clear-flash", { key: this.el.dataset.key })
  }
  this.el.style.display = "none"
}, 5000)
3 Likes

Interesting edge case! It never happened to me, but I never really stress tested my solution. Thanks for sharing the issue and your solution!

1 Like