Detect page load to get screen size, etc. using hooks

Just posting this for future me and other travelers.

In JS I was used to trying to detect the "load" event as a trigger to do stuff when the page has loaded but that has already fired by the time you would set up a listener so you can just push the event directly inside the mount function (the JS one).

In app.js

const Hooks = {
  ScreenSize: {
    mounted() {
      // If you want to listen on resize and push the same event
      window.addEventListener("resize", (e) => {
        this.pushEvent("page-size", {
          screenWidth: window.innerWidth,
          screenHeight: window.innerHeight,
        });
      });

      this.pushEvent("page-size", {
        screenWidth: window.innerWidth,
        screenHeight: window.innerHeight,
      });
    },
  },
};
// Amended boilerplate...
let csrfToken = document
  .querySelector("meta[name='csrf-token']")
  .getAttribute("content");
let liveSocket = new LiveSocket("/live", Socket, {
  params: { _csrf_token: csrfToken },
  hooks: Hooks,
});

Somewhere on the page tie in the event to the named hook. This is in a heex file or a render function. It doesn’t have to be a div.

<div phx-hook="ScreenSize" id="screen-size">

Then in your :live_view module put in a function to handle the event.

def handle_event(
        "page-size",
        %{"screenWidth" => screen_width, "screenHeight" => screen_height},
        socket
      ) do
    # Whatever your logic is ....

    {:noreply, socket}
end

As a side note (not part of the solution). if you really need to listen for a ‘done loading’ event, "phx:page-loading-stop" might work better. I can imagine this potentially being useful on the JS side, not so much the Phoenix side.

I hope this helps!

4 Likes

Just to add an option, instead of listening to resize events, you can also setup a ResizeObserver in the hook.

In this case, you get the additional flexibility of choosing whether you want to track the size of the window (rather, html element, or body element), or some specific element, such as the element the hook is attached to.

1 Like