Angular2 - поймать/подписаться на событие (щелчок) в динамически добавляемом HTML

Я пытаюсь ввести строку, содержащую событие (click), в шаблон Angular2. Строка динамически извлекается из серверной части намного позже загрузки DOM. Неудивительно, что Angular не распознает внедренное событие (click).

Пример шаблона:

<div [innerHTML]="test"></div>

Пример строки, полученной из серверной части:

var test = "When ready, <span (click)=\"itemClick($event)\">click me</span>."

Пример вызова функции в компоненте Angular:

itemClick(event) {
   debugger;
}


Следующим моим предположением было бы попробовать подписаться на Angular или поймать обычное событие javascript, поэтому тогда строка будет такой:

var test = "When ready, <span onClick=\"itemClick($event)\">click me</span>."

Конечно, я получаю сообщение об ошибке itemClick is not defined, поэтому я знаю, что он ищет эту функцию javascript.

Итак, вопрос: как я могу заставить Angular2 подписаться на это событие или функцию?


person Rhyeen    schedule 20.03.2016    source источник


Ответы (2)


Декларативное связывание событий поддерживается только в статическом HTML в шаблоне компонентов.
Если вы хотите подписаться на события динамически добавляемых элементов, вам нужно сделать это императивно.

elementRef.nativeElement.querySelector(...).addEventListener(...)

или похожие.

Если вы хотите быть безопасным для WebWorker, вы можете внедрить Renderer

constructor(private elementRef:ElementRef, private renderer:Renderer) {}

и использовать вместо этого

this.renderer.listen(this.elementRef.nativeElement, 'click', (event) => { handleClick(event);});

зарегистрировать обработчик события.

см. также Динамическое добавление прослушивателя событий в Angular 2

person Günter Zöchbauer    schedule 20.03.2016
comment
Я просто хотел бы добавить, что, поскольку приведенный выше код выполняется внутри компонента (о чем свидетельствует тот факт, что Гюнтер использует ElementRef и/или Renderer), он выполняется внутри зоны Angular, поэтому после срабатывания обработчика события щелчка Angular обнаружение изменений всегда будет выполняться (по желанию). (Если вместо этого вы прикрепите обработчик событий вне Angular, он не будет работать должным образом.) - person Mark Rajcok; 21.03.2016
comment
Нужно ли нам отменять регистрацию слушателя в ngOnDestroy(), если мы используем addEventListener() или listen()? - person Mark Rajcok; 22.03.2016
comment
Я предполагаю - да, но я никогда не уверен в этом. Обычно, если вы запрашиваете ресурс императивно, вы должны освободить его, чтобы быть в безопасности. - person Günter Zöchbauer; 22.03.2016
comment
По-видимому, Renderer.listen() вернет функцию, которая удалит слушателя (это удобно). Пример см. в ответе Эрика: stackoverflow.com/a/35082441/215945 - person Mark Rajcok; 28.04.2016
comment
Благодарю вас! У меня возникает точно такая же проблема, и я не совсем понимаю, как добавить прослушиватель для события click для определенного диапазона. Например тот, который задан в вопросе. - person user911; 19.05.2017
comment
Просто замените ... в elementRef.nativeElement.querySelector(...).addEventListener() на селектор CSS, соответствующий элементу, например 'span'. - person Günter Zöchbauer; 19.05.2017
comment
что там e упоминается? - person blackdaemon; 07.06.2017
comment
@blackdaemon это должно быть event. Спасибо за подсказку - исправлено. - person Günter Zöchbauer; 07.06.2017
comment
stackoverflow.com/questions/44407771/ - person blackdaemon; 07.06.2017
comment
@MarkRajcok, так нужно ли отменять их регистрацию в ngOnDestroy()? - person Zaker; 10.09.2017
comment
Это не сработает, если у вас есть дубликат сгенерированного html, например, кнопки закрытия на миниатюрах. - person Techno Cracker; 20.12.2017

У меня возникли проблемы с импортом ElementRef в моем сервисе, и я не хотел передавать туда ссылку Renderer. Эта услуга предназначена для отображения диалогового окна «Загрузка...», где через 3 секунды прикрепляется кнопка динамического закрытия. Я нашел решение, как добавить событие нажатия для этой кнопки с помощью jQuery. Надеюсь, это кому-то поможет.

(1) Добавьте jQuery в файл index.html Angular 2

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

введите здесь описание изображения

(2) Объявить $

declare var $: any;

введите здесь описание изображения

(3) Используйте jQuery Это фрагмент кода из моего сервиса:

 public async present() {
    this.isLoading = true;
    return await this.loadingController.create({message: 'Loading...'}).then(a => {
      a.present().then(() => {
        setTimeout(() => {
          a.message += '<ion-icon name="close-circle" class="alert-cancel-button"></ion-icon>';


          // Here starts jQuery usage
          $(a).click((clickedObject) => {
            if ($(clickedObject.target).hasClass('alert-cancel-button')) {
              this.dismiss();
            }
          });


        }, 3000);
      });
    });
  }

  public async dismiss() {
    return await this.loadingController.dismiss();
  }
  • Кстати $('alert-cancel-button').click(() => this.dismiss()) не сработало.
person Kroksys    schedule 11.07.2019