首页 > 解决方案 > 在 ngFor 循环中动态地将类添加到元素

问题描述

我有以下模板:

<app-subscriber 
  *ngFor="let stream of streams" 
  [stream]="stream" 
  [session]="session" 
  (speakEvents)='onSpeakEvent($event)'>
</app-subscriber>

父组件监听来自speakEvents如下的事件:

onSpeakEvent(event: any) {
    if (event.type === 'speaking') {
      this.spotlightSubscriber = event.emitter; 
      //The component emitting the event, from the ngFor repeat list.
      //Add class to this.spotlightSubscriber
    }
    else if (event.type === 'stopped_speaking') {
      //Remove class to this.spotlightSubscriber
    }
  }

如何动态地将 CSS 类添加/删除到事件发射器,它处于*ngFor循环中?

我需要一次将类添加到一个元素。

标签: angulartypescript

解决方案


基本上有两种方法可以实现您在这里想要实现的目标。

方法一:

创建一个property( indexToAppendClassTo)来跟踪你想应用类的索引。当子组件发出事件时,从该indexToAppendClassTo列表中添加或删除发出的流的索引。indexToAppendClassTo并根据此列表中流的索引的存在来应用类。

在班上:

import { Component } from '@angular/core';

@Component({...})
export class AppComponent {
  ...
  indexToAppendClassTo: any[] = [];

  onSpeakEvent(event: any, index) {
    // Approach 1
    if (event.type === 'speaking') {
      this.spotlightSubscriber = event.emitter;
      if(this.indexToAppendClassTo.indexOf(index) === -1)
        this.indexToAppendClassTo.push(index);
    } else if (event.type === 'stopped_speaking') {
      if(this.indexToAppendClassTo.indexOf(index) > -1)
        this.indexToAppendClassTo.splice(index, 1);
    }
  }
}

在模板中:

<app-subscriber 
  *ngFor="let stream of streams; let i = index;" 
  [stream]="stream" 
  [session]="session" 
  (speakEvents)='onSpeakEvent($event, i)'
  [ngClass]="indexToAppendClassTo.includes(i) ? 'color' : ''">
</app-subscriber>

方法二

正如其他人所提到的,如果您愿意发送一些属性作为决定是否应用该类的发出事件的一部分,那么从您的子组件执行此操作,然后将子组件的更新stream作为发出的$event数据传递. 这样您就不必不必要地管理indexToAppendClassTo列表:

在父组件类中:

import { Component } from '@angular/core';

@Component({...})
export class AppComponent {
  ...

  onSpeakEvent(event: any) {
    // Approach 2
    const indexOfElement = this.streams.findIndex(strem => strem.name === event.name);
    this.streams[indexOfElement] = { ...event };
  }
}

在父组件模板中:

<app-subscriber 
  *ngFor="let stream of streams" 
  [stream]="stream" 
  [session]="session" 
  (speakEvents)='onSpeakEvent($event)'
  [ngClass]="stream.type === 'speaking' ? 'color': ''">
</app-subscriber>

在子组件类中:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-subscriber',
  templateUrl: './subscriber.component.html',
  styleUrls: ['./subscriber.component.css']
})
export class SubscriberComponent implements OnInit {

  @Input() stream;
  @Input() session;
  @Output() speakEvents: EventEmitter<any> = new EventEmitter<any>();

  ...

  onClick() {
    this.speakEvents.emit({ ...this.stream, type: 'type of the stream here' });
  }

  ...

}

在子组件模板中:

<button (click)="onClick()">{{stream.name}}</button>

这是一个工作示例 StackBlitz,其中包含供您参考的两种方法。


推荐阅读