Possible to attach event handlers to widgets in theme/plugin?

Hi,

I’m looking to add a click handler to items in the main topic list (to add custom behavior under some conditions). Is it possible to use something like api.decorateWidget() to add an event handler to every instance of a particular widget?

Other approaches considered:

  • It’s not practical to use addEventListener in a global function because additional topic list items can be loaded after page load, e.g. infinite scroll. (the implementation would need to use something like MutationObserver to observe changes in the DOM and attach more events handlers as more widgets render)
  • It could be possible to attach a click handler to body and monitor through event bubbling (e.g. as done through jQuery with $("body").on("click", ".list-item-topic", function())), but I need to be able to use preventDefault() and stopPropagation(), which I believe this approach doesn’t support
1 Like

api.attachWidgetAction is the way to go. You can read search the codebase and you’ll be gtg.

Examples here

Ah, thank you! Are these standard DOM events? i.e.:

  • From the examples, it doesn’t seems like the events are standard DOM events like click, mouseover, etc. Is it possible to do e.g. api.attachWidgetAction("topic-list-item", "click", ...)?
  • Is it possible to access event, e.g. to do event.stopPropagation()?
  • If this aren’t standard DOM events, how do I find out which events a particular widget broadcasts?

Thanks for the pointers!

Additionally: a little confused here, but how do I find the “widget” associated with a particular UI element? (in my case: the widget powering topic-list-item showing an individual topic in a topic list). From the widget directory, none seem related to topic-list-item. This “component” seems to be instead be responsible for rendering topic-list-item.

Not clear about the distinction between widgets and components (apologies for not being more familiar) — presumably it’s only possible to attach event handlers with api.attachWidgetAction to “widgets” but not to “components”. Is there an equivalent for components?

About the Widget and Component:

1 Like

Thanks all! Figured it out.

For others in the future looking to override event handlers for components, add the following to javascripts/your-plugin-name/initializers/script-name-of-your-choice.js.es6:

import { withPluginApi } from "discourse/lib/plugin-api";

export default {
  name: "custom-click-handler",

  initialize() {
    withPluginApi("0.8.20", (api) => {
      api.modifyClass("component:topic-list-item", {
        click(e) {
          ...
        }
      });
    });
  },
};
4 Likes