Get JS notification if LiveView did not push a change

Hi there

I’ve got a legacy application where I’ve recently rewritten the search into a LiveComponent. Because the searches can take some time, we are showing an overlay that is triggered from JS using a hook. The overlay is later cleared in an update function in the same hook, i.e. like this:

hooks = {
  mounted: {
    document.addEventListener("some-user-event", e => {
      this.el.querySelector("overlay").classList.remove("disabled")
      this.pushEvent(...);
    });
  },
  updated: {
    this.el.querySelector("overlay").classList.add("disabled")
  }
}

However we’ve now got the situation that, if the user searches for the same input again, we’ll show the overlay, but LiveView will correctly not push any changes, so the overlay is never cleared.

However I’ve noticed that the websocket actually receives a reply from the server, that just does not trigger the updated hook. So my idea was, is there some way to have a hook that triggers if a msg was received, but did not change anything? Then I could clear the overlay there.

Hi clemensm,

I’m also using LiveView and from what I know up to now I don’t think it is possible to do exactly what you described. However, if what you want is a class change, LiveView already offers this with phx-*-loading which adds a class to the element while the action is being performed and removes it afterwards. https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html#module-loading-state-and-errors

If however you want a custom handler of that, the only way I can think of is doing a workaround by having some counter that changes on every update and that way even if the input hasn’t changed, it will update the element. Also, the socket element has a changed key, which you could also use to see if there was or not any change and maybe you could trigger an update comparing that key with other stuff.

Hope this helps.

Hmm, that would work if I could use phx-bindings. Sadly parts of the control are still implemented as a WebComponent, so I’m pusing the search queries manually from a hook. And looking at the source code is seems that no class is set in that case…

But thanks anyway, I think I’ll open a feature request for this.

Edit: See here for gitlab issue

1 Like

Yeah, I think it would be nice to have something like that available through hooks too. However, those part of the control you are talking about, are they being triggered by JS? I am asking because if you have any HTML inside a LiveView (even if generated by something else) you can also add the bindings directly on the HTML and it should work.

That would be possible, of course. The problem is that I couldn’t rewrite all parts of the component, so inside the component there’s still one part that is implemented as a WebComponent, with it’s content provided by a <template>. And the template is appended to the shadow root of the nested component, so those events won’t bubble upwards to the LiveView…

But I might give it another try with slots, maybe that could work.