Phoenix LiveView - animate page updates

Hey :slight_smile:

I’ve been using LiveView on and off for a while - I find that it’s really amazing for dashboards where I need live updated data. For example, I have a phoenix application with Broadway which reads from a rabbitmq queue, processes the json messages flowing through it and updates some stats counters I store in ETS.

With a table full of numbers changing on the screen it can be hard for a user to see the important stuff - ie. what parts are changing.

I’d like to present the solution I came up with, and start a discussion about better ways to do this.

in my live views I add a class “show_updates” where I want to see updates.

<span class="show_updates"> <%= @throughput %> events per second </span>

In my css I have an animation eg.

.live_view_updated {
  animation-name: flash;
  animation-duration: 1.0s;
}

@keyframes flash {
  0%   {background-color: inherit;}
  5%  {background-color:rgb(241, 241, 241);}
  100% {background-color: inherit;}
}

And in my app.js I have the following;

let liveViewDirty = false; // tracks if we have any live_view_updated classes to clear

let liveSocket = new LiveSocket("/live", Socket, {
  params: {
    _csrf_token: csrfToken
  },
  dom: {
    onBeforeElUpdated(from, target){
      if(target.classList.contains("show_updates")) {
        if (from.textContent != target.textContent) {
          target.classList.add("live_view_updated");
          liveViewDirty = true;    
        }
      }
    }    
  }
});

window.setInterval(() => {
  if(liveViewDirty) {
    let updated = document.querySelectorAll('.live_view_updated');
    updated.forEach((node) => {
      node.classList.remove("live_view_updated")
    });
    liveViewDirty = false;
  }
}, 450);

when an element is updated by morphDom, I check if the element has the class “show_updates” in which case I add the class “live_view_updated” and mark liveViewDirty = true;

This triggers the animation.

every 450ms I poll and check if liveViewDirty is true, and if so, I remove the live_view_updated class.

What shows on the screen is a nice background flash of the elements that are updated.

The downside is because I’m polling, sometimes an animation isn’t complete and gets cancelled when the live_view_updated class is removed - so some elements don’t flash. It doesn’t happen too often though, so it mostly works. If I don’t clear the class often enough it might miss animating the subsequent update.

I just wondered if anyone else has any alternative ways to do this or any suggestions?

I guess I could add another class with a uuid and then trigger a setInterval to clean it up after the animation ends but this would couple my js timing with my css timing and having so many intervals could get expensive.

I’m a bit of a javascript / css rookie so any suggestions would be appreciated.

2 Likes

:eyes: Ha! Watching as I did the exact same thing pre-LiveView and need to figure out how to implement with LiveView at some point.

1 Like