Я не могу получить доступ к элементу DOM, который я создаю с помощью цикла ngFor, и я получаю данные из сервиса. Angular

#javascript #arrays #angular #dom #service

#javascript #массивы #угловатый #дом #Обслуживание

Вопрос:

Я столкнулся с проблемой, связанной с манипуляцией DOM в angular. Я определил один массив с именем colors в своем компоненте, а затем вызываю метод service и получаю данные о цветах с сервера, а затем присваиваю их массиву colors внутри метода subscribe. В HTML-шаблоне, использующем цикл *ngFor, я отображаю данные массива цветов. Теперь я хочу добавить некоторый динамический класс или стиль к элементам HTML, и для этого я использую ElementRef для доступа к этому элементу, но я не могу получить к нему доступ, потому что массив цветов изначально не определен. Теперь позвольте мне приложить код…

 @Component({
  selector: 'app',
  template: "<div><li class="color" *ngFor="let color of colors">{{color}}</li></div>",
  styleUrls: ['./app.component.css'] 
})

export class AppComponent implements OnInit, AfterViewInit {
   colors:any;

   constructor(private elementRef:ElementRef, private renderer:Renderer2) {}
   
   ngOnInit():void {
     setTimeout(() => {
        this.colors = ['red', 'yellow', 'green'];
     }, 1000);
   }

   ngAfterViewInit():void {
     const color = this.elementRef.nativeElement.querySelectorAll('.color');
     console.log(color);
   }
}
 

Здесь я использую функцию setTimeout в этом коде, которая ведет себя как служба, потому что службе требуется некоторое время для получения данных с сервера, но в моем коде я использую service .

Теперь, если я открываю консоль в инструментах разработчика, я получаю NodeList [] это означает, что я не могу получить доступ к элементу DOM. Я знаю проблему, я не могу получить доступ к элементу DOM, потому что мой код для доступа к элементу DOM выполняется до назначения данных массиву цветов, а по умолчанию или изначально массив цветов не определен или пуст. Вот почему я получаю NodeList [] в консоли. Но я не в состоянии понять, как решить эту проблему?.

Заранее благодарю.

Ответ №1:

Вам нужно ngAfterViewCHecked . Это будет выполняться каждый раз, когда Angular завершит выполнение обнаружения изменений в компоненте и его дочерних элементах

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

 '<div><li class="color" *ngFor="let color of colors">{{color}}</li></div>'
 

ДЕМОНСТРАЦИЯ

Комментарии:

1. да, но проблема с ngAfterViewChecked заключается в том, что он каждый раз запускает весь код внутри этого и делает приложение запаздывающим или медленным, например: проверьте эту ссылку на код: stackblitz.com/edit/angular-ivy-qsy5ma?file=src/app /…

Ответ №2:

Это происходит потому ngAfterViewInit , что завершаются вызовы до истечения установленного вами тайм-аута ngOnInit .

Я бы выбрал ViewChildren более надежный подход.
Вот один из примеров:

 @Component({
  selector: "my-app",
  template: `
    <ul>
      <li #color *ngFor="let color of (colors$ | async)">{{ color }}</li>
    </ul>
  `,
  styles: []
})
export class AppComponent implements OnDestroy, AfterViewInit {
  @ViewChildren("color") colors: QueryList<ElementRef<HTMLLIElement>>;
  colors$: Observable<string[]> = of(["red", "green", "blue"]).pipe(
    delay(3000)
  );

  private colorsSubscription = Subscription.EMPTY;

  ngAfterViewInit(): void {
    this.colors.changes.subscribe(list => {
      list.forEach(element => {
        console.log(element.nativeElement);
      });
    });
  }

  ngOnDestroy(): void {
    this.colorsSubscription.unsubscribe();
  }
}
 

То, что мы делаем в этом примере, это:

  • Инициализация colors$ для запуска строкового массива через 3 секунды
  • Подписка на colors$ с AsyncPipe помощью и отображение цветов
  • Настройка ViewChildren запроса для всех элементов со #color ссылкой на шаблон
  • Подписка на QueryList изменения (добавления / удаления и т.д.) и соответствующие действия

Вы можете найти полный пример в этом стекблите

Комментарии:

1. да, но если я пытаюсь получить доступ к первому элементу, используя этот код внутри метода ngAfterViewInit. код: console.log(this.colors. toArray[0].nativeElement); Я не могу получить к нему доступ, тогда как я добавлю новый стиль к этому элементу.

2. Это связано с тем, что вы не можете получить доступ к списку в разделе изменения по индексу. Вы можете, например, перебирать элементы, используя forEach . Я обновил пример, чтобы показать это.