# Можно ли прикреплять обработчики событий к виджетам в теме/плагине?

**URL:** https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204
**Category:** Development
**Created:** [04.Октябрь.2020 15:42:58 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204 "2020-10-04T15:42:58Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![dchouinard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dchouinard/32/194662_2.png) [@dchouinard](https://meta.discourse.org/u/dchouinard)
#### Post date: [04.Октябрь.2020 15:42:58 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204/1 "2020-10-04T15:42:58Z")

</div>

Привет,

Я хочу добавить обработчик клика для элементов в основном списке тем (чтобы реализовать пользовательское поведение при определённых условиях). Возможно ли использовать что-то вроде `api.decorateWidget()`, чтобы добавить обработчик событий к каждому экземпляру определённого виджета?

—

Рассмотренные альтернативные подходы:

- Использовать `addEventListener` в глобальной функции непрактично, так как дополнительные элементы списка тем могут загружаться после загрузки страницы, например, при бесконечной прокрутке. (В таком случае реализация потребовала бы использования `MutationObserver` для отслеживания изменений в DOM и добавления новых обработчиков событий по мере рендеринга новых виджетов)
- Теоретически можно добавить обработчик клика к `body` и отслеживать события через всплытие (как это делается в jQuery с помощью `$("body").on("click", ".list-item-topic", function())`), но мне нужно иметь возможность вызывать `preventDefault()` и `stopPropagation()`, и, насколько я понимаю, этот подход не поддерживает такие методы.

---

<div class="post-metadata">

### Author: ![fzngagan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/fzngagan/32/259349_2.png) [@fzngagan](https://meta.discourse.org/u/fzngagan)
#### Post date: [04.Октябрь.2020 15:49:06 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204/2 "2020-10-04T15:49:06Z")

</div>

> [@dchouinard](#):
>
> Я хочу добавить обработчик клика к элементам списка тем (чтобы добавить пользовательское поведение при определённых условиях). Можно ли использовать что-то вроде `api.decorateWidget()`, чтобы добавить обработчик событий ко всем экземплярам конкретного виджета?

Лучше использовать `api.attachWidgetAction`. Вы можете поискать в коде, и у вас всё получится.

Примеры [здесь](https://github.com/search?q=org%3Adiscourse+api.attachWidgetAction&type=code)

---

<div class="post-metadata">

### Author: ![dchouinard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dchouinard/32/194662_2.png) [@dchouinard](https://meta.discourse.org/u/dchouinard)
#### Post date: [04.Октябрь.2020 15:57:28 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204/3 "2020-10-04T15:57:28Z")

</div>

Ах, спасибо! Это стандартные события DOM? То есть:

- Судя по примерам, события не кажутся стандартными событиями DOM, такими как `click`, `mouseover` и т.д. Можно ли, например, выполнить `api.attachWidgetAction("topic-list-item", "click", ...)`?
- Можно ли получить доступ к объекту `event`, например, чтобы вызвать `event.stopPropagation()`?
- Если это не стандартные события DOM, как узнать, какие события транслирует конкретный виджет?

Спасибо за подсказки!

---

<div class="post-metadata">

### Author: ![dchouinard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dchouinard/32/194662_2.png) [@dchouinard](https://meta.discourse.org/u/dchouinard)
#### Post date: [04.Октябрь.2020 16:15:13 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204/4 "2020-10-04T16:15:13Z")

</div>

Кроме того, я немного запутался: как найти «виджет», связанный с определённым элементом UI? (В моём случае — виджет, отвечающий за отображение элемента списка тем topic-list-item, который показывает отдельную тему в списке тем). В [каталоге виджетов](https://github.com/discourse/discourse/tree/master/app/assets/javascripts/discourse/app/widgets) ни один, похоже, не относится к topic-list-item. [Этот «компонент»](https://github.com/discourse/discourse/blob/52672b9eabccb1184d85dc7f08062d5a7c18cb73/app/assets/javascripts/discourse/app/components/topic-list-item.js), похоже, отвечает за рендеринг topic-list-item.

Мне неясно различие между виджетами и компонентами (извините за мою неосведомлённость) — предположительно, обработчики событий можно прикреплять через `api.attachWidgetAction` только к «виджетам», но не к «компонентам». Существует ли аналог для компонентов?

---

<div class="post-metadata">

### Author: ![hawm](https://avatars.discourse-cdn.com/v4/letter/h/f07891/32.png) [@hawm](https://meta.discourse.org/u/hawm)
#### Post date: [04.Октябрь.2020 17:22:28 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204/5 "2020-10-04T17:22:28Z")

</div>

О виджете и компоненте:

> [@How different are Ember component and Discourse widget?](https://meta.discourse.org/t/how-different-are-ember-component-and-discourse-widget/154174/2):
>
> Components are broadly used across most of Discourse. Where widgets come in useful is on some of our most highly-trafficked elements, such as the topic post stream and the header with its multiple menus. You’ll often see widgets used in plugins and themes to add to or modify existing widgets. Take for example this widget in the discourse-calendar plugin: This is a button rendered in the original post of a topic. It needs to be a widget because the post itself is rendered as a widget for per…

---

<div class="post-metadata">

### Author: ![dchouinard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dchouinard/32/194662_2.png) [@dchouinard](https://meta.discourse.org/u/dchouinard)
#### Post date: [04.Октябрь.2020 17:56:53 UTC](https://meta.discourse.org/t/possible-to-attach-event-handlers-to-widgets-in-theme-plugin/166204/6 "2020-10-04T17:56:53Z")

</div>

Спасибо всем! Разобрался.

Для тех, кто в будущем захочет переопределить обработчики событий для компонентов, добавьте следующее в `javascripts/ваше-имя-плагина/initializers/выбранное-имя-скрипта.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) {
          ...
        }
      });
    });
  },
};

```
