Does LiveComponent intercept "click" events?

I have an html element inside of LiveComponent. It’s not “converted” to Phoenix LiveView or LiveComponent element yet (no phx-click added), so still relies on class name and jQuery event listener.

<a href="#" class="comment-control-reply"><%= gettext "reply" %></a>

$(commentControlReply).on("click", function(e) { console.info(e) })

This worked when it was not a child of LiveComponent. Is being a child element of LiveView or LiveComponent interferes with normal flow of events?

:wave:

It probably doesn’t but a.comment-control-reply might get patched so that the event listener might not be there when the element is clicked. A way around this is to set the event listener in a hook for this element.

<a href="#" class="comment-control-reply" phx-hook="CommentControlReplyHook"><%= gettext "reply" %></a>
const CommentControlReplyHook = {
  mounted() {
    $(this.el).on("click", function(e) {console.info(e)})
  }
};
export default CommentControlReplyHook;
1 Like

Thanks!

I will try it.

What do you mean by patched? Where can I read more about this behavior of LiveView?

I thought that LiveView only works (in this case patches) when we add “phx” attributes to html elements.

What do you mean by patched?

I mean DOM patching done via morphdom which live view uses to keep the client and the server views in sync. So if the server decides to updates some part of DOM, the event listeners that have been set for those elements might get lost.

Where can I read more about this behavior of LiveView?

Phoenix.LiveView — Phoenix LiveView v0.20.2 might be helpful.

2 Likes

A “DOM Patch” means roughly that elements might be added, altered or removed (by LiveView, because the content of the page has to change).
If you have a JQuery event listener such as $(".myclass").on("click", function() {...}); then this will only be added to all elements with the class attribute myclass at the time it is invoked. If other elements are added later (or other elements are altered to also get the class “myclass” later), then those will not trigger the event listener. See also the documentation of jQuery’s .on method:

Event handlers are bound only to the currently selected elements; they must exist at the time your code makes the call to .on()

There are two solutions for this problem:

  1. Use the Phoenix LiveView hooks such as what @idi527 already showed. This is probably the cleanest solution.
  2. Use a jQuery ‘delegated event handler’, like $(".container-outside-of-liveview").on("click", ".comment-control-reply", function() {...}). See the documentation of .on for more information on this, which I think should work as well (I have not tested it myself, however).
3 Likes

thanks a lot!

Both solutions work. Ended up using hooks, but good to know about delegated event handlers too.

2 Likes