Как вызвать addeventlistner для this.el.nativeelement.queryselector ('selector'), где el - elementref

Я использую angular 5 и имею простое требование, когда мне нужно создать некоторый html внутри функции, а затем зациклить его, чтобы привязать к ним событие щелчка.

Раньше занимался:

userslist.component.ts

import { Component, Input, ElementRef} from '@angular/core';
enter code here
 constructor(private el: ElementRef){}

createUserList(){

    this.userList= _cityList.map(list => {
      return `<li class="list-users" >${list.display_name}<span class="hide" >${list.name}</span></li>`;
    }).join('');

this.el.nativeElement.querySelectorAll('li.list-users').forEach(ele => {

 ele.addEventListener('click', this.selectUsers.bind(this));
}

} При этом я получаю ошибку в IE:

ERROR TypeError: Object doesn't support property or method 'forEach'

Поэтому я обновил его до:

  const listUsers= Array.from(document.querySelectorAll(".list-users"));

        listUsers.forEach((ele) => {
          ele.addEventListener('click', this.selectUsers.bind(this));
        })

это работало в IE и других браузерах. Но я не хочу использовать документ для доступа к элементам DOM.

Если я напишу:

   const listUsers= Array.from(this.el.nativeElement.querySelectorAll(".list-users"));

        listUsers.forEach((ele) => {
          ele.addEventListener('click', this.selectUsers.bind(this));
        })

Затем я получаю ошибку в tslint:

Property 'addEventListener' does not exist on type '{}'

Вывод как this.el.nativeElement.querySelectorAll (". List-users"), так и document.querySelector одинаков.

Тогда почему Array.from не преобразовывает прежний в массив.

Нужна помощь в исправлении этого с помощью углового способа, а не использования объекта документа напрямую.

вывод я получаю от обоих:

NodeList(5)  0:li.list-users
1:li.list-users
2:li.list-users
3:li.list-users
4:li.list-users

Спасибо!

Как выглядит ваш HTML?

Rusty 10.08.2018 15:21

<li class = "list-users"> $ {list.display_name} <span class = "hide"> $ {list.name} </span> </li>. Пять таких элементов списка. обновленный вопрос. Спасибо.

Alwaysalearner 10.08.2018 15:25
0
2
827
2

Ответы 2

Для начала перестаньте использовать ванильный JS.

Angular - это полноценный фреймворк, который также поддерживает динамические манипуляции с DOM через свой Renderer.

Во-вторых, в этом случае вместо средства визуализации следует использовать декоратор ViewChildren.

Этот stackblitz показывает, как это работает. Откройте консоль и щелкните по элементам.

import { Component, Input, Renderer2, QueryList, ViewChildren, ElementRef } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<ul>
        <li *ngFor="let i of [0, 1, 2, 3]" #listItems>Index is {{ i }}</li>
      </ul>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent {
  @Input() name: string;

  @ViewChildren('listItems') listItems: QueryList<ElementRef<HTMLUListElement>>

  constructor(private R: Renderer2) {
  }

  ngAfterViewInit() {
    this.listItems.toArray().forEach((item, index) => {
      this.R.listen(item.nativeElement, 'click', () => {
        console.log('You clicked on the item n° ', index);
      });
    });

  }
}

Спасибо trichetriche Но я динамически создаю HTML. Я обновил свой вопрос. благодаря. с этим тоже будет работать?

Alwaysalearner 10.08.2018 15:36

@Simer, ответ тот же: перестаньте делать это в ванильном стиле JS и используйте Angular для динамического создания элементов списка.

user4676340 10.08.2018 15:37

Я получаю ERROR TypeError: Невозможно прочитать свойство toArray, равное undefined. Может быть, это потому, что я создаю html с функцией, а затем вызываю toArray в этой функции, и код работает асинхронно, и к тому времени html еще не готов.

Alwaysalearner 10.08.2018 15:44

Если вы продолжали это делать, то да, это нормально. Как я уже сказал, вы должны поместить элементы списка в шаблон и использовать Angular для его заполнения. Посмотрите на stackblitz и добавьте к нему свои данные, это будет легче понять.

user4676340 10.08.2018 15:46

Но я не хочу, чтобы они были в шаблоне, который они генерируют динамически. Да, я проверил stackblitz, и он работает нормально. но мое требование - небольшая разница. нет. of li генерируется динамически на основе некоторого результата, который я получаю с сервера, поэтому каждый раз, когда у меня нет различий. элементов Ли. вот почему создание элементов li внутри функции компонента. Извините, но я не знаю, как я могу сделать это угловым способом.

Alwaysalearner 10.08.2018 15:49

Вы можете сделать это с помощью *ngFor. Если вы устанавливаете angular и не используете его, то вам вообще не следует устанавливать его! Подумайте о прочтении документации об этом или, возможно, о переключении фреймворков (например, jquery, react или vue)

user4676340 10.08.2018 15:51

trichetriche Мне нужна еще одна помощь. Если вы можете сказать мне, как я могу привязать конкретную функцию к событию щелчка liItems. Как я сделал ранее в своем вопросе. Я пытаюсь реализовать ваше решение.

Alwaysalearner 10.08.2018 16:09

Позвольте нам продолжить обсуждение в чате.

Alwaysalearner 10.08.2018 16:15

Я говорю по телефону, извините, я не могу поболтать. Но вам просто нужно заменить журнал консоли на нужную функцию! Это может быть даже функция вашего компонента.

user4676340 10.08.2018 16:16

Извините, я задал неправильный вопрос. Я знаю, как это сделать. Спасибо за помощь. Бог благословил!

Alwaysalearner 10.08.2018 16:18

Вы можете использовать метод прослушивания @ViewChildren и Renderer2 для обработки события щелчка. Вот код stackblitz. https://stackblitz.com/edit/angular-vzduhs

Вместо того, чтобы копировать существующий ответ, подумайте о том, чтобы проголосовать за него. Дубликаты бесполезны.

user4676340 10.08.2018 15:35

Я не говорю, что вы его скопировали, я говорю, что это тот же ответ. И если это тот же ответ, вам следует подумать о том, чтобы проголосовать за уже существующий, вместо того, чтобы публиковать тот же ответ. Это просто здравый смысл ...

user4676340 10.08.2018 15:36

Другие вопросы по теме