DEV Community

Cover image for Connectivity status with Phoenix LiveView
NDREAN
NDREAN

Posted on • Updated on

Connectivity status with Phoenix LiveView

Some notes on how to display - outside of a LiveView - the status of the connection by rendering images using the callback onBeforeElUpdated.

We define an <img> tag somewhere in "root.html.heex" or "app.html.heex" and want to set its src attribute depending upon the connection status, "online" or "offline".

<img width="30px" alt="line-status" id="online-status" />
Enter fullscreen mode Exit fullscreen mode

The connection status is accessible in the browser with the navigator.onLine boolean.

The connection change is captured by the window interface events online and offline.

We define the callbacks to these events: we append a given image file to the src attribute with some styling.

// /assets/js/onlineStatus.js

const domEl = document.getElementById("online-status");

const status = {
  online: { src: "/images/online.svg", bg: "lavender", opacity: 0.8 },
  offline: { src: "/images/offline.svg", bg: "tomato" },
};

const setOnline = (el, { opacity = 1, bg, src }) => {
  el.style.opacity = opacity;
  el.src = src;
  el.style.backgroundColor = bg;
};

const statusListener = () => {
  window.onoffline = () => setOnline(domEl, status.offline);
  window.ononline = () => setOnline(domEl, status.online);
};


export { statusListener };
Enter fullscreen mode Exit fullscreen mode

We import and use this function in our Javascript "app.js" file:

// /assets/js/app.js

import {statusListener} from "./onlineStatus.js"

statusListener()
Enter fullscreen mode Exit fullscreen mode

It remains to solve the first render problem. Indeed, unless we set a initial src attribute on the <img> element above, which we don't want, the LiveView DOM patching won't rendering anything. The snippet below doesn't work:

navigator.onLine ? setOnline(domEl, status.online) : setOnline(domEl, status.offline)
Enter fullscreen mode Exit fullscreen mode

This can be solved with the onBeforeElUpdated callback. It lets you perform your own DOM patching, independently from LiveView, on whatever DOM element you name from into a transformed DOM element named to.
This callback is attached to the dom property of the LiveSocket under the key onBeforeElUpdated. It looks like this:

We add a say firstRender function in our custom JS file and add our snippet:

// /assets/js/onlineStatus.js

const firstRender = (from, to) => {
  if (from.getAttribute("id") === "online-status") {
    navigator.onLine
      ? setOnline(to, status.online)
      : setOnline(to, status.offline);
  }
}

export {firstRender, statusListener }
Enter fullscreen mode Exit fullscreen mode

and then append it to our LiveSocket in the "app.js":

// /assets/js/app.js
import {statusListener, firstRender} from "./onlineStatus.js"

const liveview = new LiveSocket("/live", Socket, {
  longPollFallbackMs: 2500,
  params: { _csrf_token: csrfToken },
  dom: { onBeforeElUpdated: firstRender },
  },
});

liveview.connect();
onlineStatus();
[...]
Enter fullscreen mode Exit fullscreen mode

Examples of SVGs

The "/priv/static/images/online.svg" file example:


<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path xmlns="http://www.w3.org/2000/svg" d="M 5.78125 4.1875 C 3.48125 6.0215 2 8.837 2 12 C 2 15.163 3.48125 17.9785 5.78125 19.8125 L 7.03125 18.25 C 5.19125 16.783 4 14.53 4 12 C 4 9.47 5.19125 7.217 7.03125 5.75 L 5.78125 4.1875 z M 18.25 4.1875 L 17 5.75 C 18.83 7.218 20 9.477 20 12 C 20 14.523 18.83 16.782 17 18.25 L 18.25 19.8125 C 20.538 17.9775 22 15.154 22 12 C 22 8.846 20.538 6.0215 18.25 4.1875 z M 8.28125 7.3125 C 6.90125 8.4125 6 10.102 6 12 C 6 13.898 6.90125 15.5875 8.28125 16.6875 L 9.53125 15.125 C 8.61225 14.391 8 13.265 8 12 C 8 10.735 8.61225 9.609 9.53125 8.875 L 8.28125 7.3125 z M 15.75 7.3125 L 14.5 8.90625 C 15.416 9.64025 16 10.739 16 12 C 16 13.262 15.415 14.36075 14.5 15.09375 L 15.75 16.6875 C 17.122 15.5875 18 13.892 18 12 C 18 10.108 17.123 8.4135 15.75 7.3125 z M 12 10.5 C 11.171573 10.5 10.5 11.171573 10.5 12 C 10.5 12.828427 11.171573 13.5 12 13.5 C 12.828427 13.5 13.5 12.828427 13.5 12 C 13.5 11.171573 12.828427 10.5 12 10.5 z"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

The "/priv/static/images/offline.svg" example:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path xmlns="http://www.w3.org/2000/svg" d="M 3.90625 2.28125 L 2.5 3.71875 L 4.34375 5.5625 C 2.8847559 7.2990879 2 9.55875 2 12 C 2 15.162 3.48125 17.9785 5.78125 19.8125 L 7.03125 18.25 C 5.19125 16.783 4 14.53 4 12 C 4 10.111392 4.6813379 8.3690147 5.78125 7 L 7.1875 8.40625 C 6.44465 9.4038808 6 10.663008 6 12 C 6 13.898 6.90125 15.5875 8.28125 16.6875 L 9.53125 15.09375 C 8.61225 14.35975 8 13.265 8 12 C 8 11.214008 8.2597973 10.490055 8.65625 9.875 L 10.53125 11.75 C 10.517412 11.831789 10.5 11.91425 10.5 12 C 10.5 12.828 11.172 13.5 12 13.5 C 12.08575 13.5 12.168169 13.482588 12.25 13.46875 L 20.5 21.71875 L 21.90625 20.28125 L 3.90625 2.28125 z M 18.25 4.1875 L 17 5.75 C 18.83 7.217 20 9.477 20 12 C 20 13.194 19.722 14.2945 19.25 15.3125 L 20.71875 16.8125 C 21.51475 15.3805 22 13.751 22 12 C 22 8.846 20.538 6.0215 18.25 4.1875 z M 15.75 7.3125 L 14.5 8.875 C 15.416 9.609 16 10.738 16 12 C 16 12.027 16.001 12.0355 16 12.0625 L 17.71875 13.78125 C 17.89975 13.21225 18 12.628 18 12 C 18 10.108 17.123 8.4135 15.75 7.3125 z"/>
</svg>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)