Stop the propagation of click events while still keeping phx-click binding

Hi there!

I recently finished building a multi select. I am using Alpine.js to open a dropdown where the user can select certain options that are displayed as badges in the select. In addition, the user can delete options by clicking on an x icon displayed in the badge. The deletion is implemented using a phx-click binding. The problem now is that every time the user clicks on the icon, the dropdown closes because the Alpine.js click event is propagated to all child elements. I have found that I can stop the propagation by calling the Event#stopPropagation method, but this breaks my phx-click. How can I stop Alpine.js click event propagation while still keeping the phx-click?

Thanks in advance!

From your description, it sounds more like the click event from the LiveView phx-click on the child x icon is bubbling up to the parent dropdown that uses Alpine.js to open and close. If that’s true, then what you want it to stop the click event handler on the child x icon to stop the click event from propagating.

As far as I know, there isn’t a way to configure phx-click to not propagate an event at the moment. `phx-click` event bubbles down to child inputs · Issue #557 · phoenixframework/phoenix_live_view · GitHub

Instead, you could manually set up a client side hook and click event listener that pushes the click event to the server as well as stopping event propagation. It might look something like:

mounted() {
  this.el.addEventListener("click", e => {
      e.stopPropagation(); // or maybe e.preventDefault();
      this.pushEvent("delete", {id: this.el.id}); // or ... {id: e.target.id});
    }
  })
}

Edited to add:
It looks like Alpine.js includes a .self modifier for x-on that may come in handy.

.self

By adding .self to an event listener, you are ensuring that the event originated on the element it is declared on, and not from a child element.

<button @click.self="handleClick">    Click Me     <img src="..."></button>

In the above example, we have an <img> tag inside the <button> tag. Normally, any click originating within the <button> element (like on <img> for example), would be picked up by a @click listener on the button.

However, in this case, because we’ve added a .self, only clicking the button itself will call handleClick. Only clicks originating on the <img> element will not be handled.