Liveview JS hooks

Hello everyone,

I am trying to hook some js to Phoenix LiveView (0.8.1)

I have a template like this

<a phx-click="toggle">Click</a>

<%= if @active do %>
  <div id="VideoPlayer">Loading the player...</div>
  <div phx-hook="Player">hook</div>
<% end %>

The toggle event switch the value of @active. and the hook is responsible for loading jwplayer in the VideoPlayer div.

The hook is like this

Hooks.Player = {
  mounted() {
    console.log("Player Mounted")
    let jwplayer = window.jwplayer

    let playerElement = document.getElementById("VideoPlayer")
    if (playerElement) {
      jwplayer.key = "my key"
      let playerInstance = jwplayer(playerElement)
      console.log(playerInstance)

      let jwconfig = { /* jwplayer config object */}
      playerInstance.setup(jwconfig)
    }
  },
  updated() {
    console.log("Player Updated")
  },
  destroyed() {
    console.log("Player Destroyed")
  }
}

It is working fine, JS is triggered correctly and the video player starts to play. My question is what happens when the player is removed?

I wanted to clean the player with this code in the destroyed hook event. This remove the player, but not the loading div. (console show correct message, but page show Loading the player…)

    let jwplayer = window.jwplayer
    let playerElement = document.getElementById("VideoPlayer")
    if (playerElement) {
      console.log("Player Destroyed")
      jwplayer(playerElement).remove();
    }

Why not cleaning works fine, but cleaning the player on destroy leave the div in place? Is it because I morphed DOM prior to remove?

Is it safe not to clean up on destroy?

Thanks for taking time

2 Likes

Currently you clean up the video player but not the div. This is probably safe. Not cleaning up either is ‘safe’ as well, but in the worst case you might leak some memory which might slow down a visitors computer if a video is very frequently loaded/unloaded or the app stays open for a long time.

I have not tested your code myself, but this might be related to the fact that the element that your phx-hook is on is a sibling of the #VideoPlayer element. I believe that the JS interop is meant to work with the children of the HTML element that has the phx-hook set.

1 Like

Thanks, changing the template to this solved the problem :slight_smile:

  <div phx-hook="Player">
    hook
    <div id="VideoPlayer">Loading the player...</div>
  </div>

With this I can properly remove the player on destroy with less fear of memory leak.

3 Likes