There are essentially two methods to achieve the desired outcome here.
Method 1:
To track the indexes where you want to apply a class, create a property (indexToAppendClassTo
). When the Child Component emits an event, add or remove the index of the emitted stream from this indexToAppendClassTo
list. Apply the class based on the presence of the index in this list.
In Class:
import { Component } from '@angular/core';
@Component({...})
export class AppComponent {
...
indexToAppendClassTo: any[] = [];
onSpeakEvent(event: any, index) {
// Method 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);
}
}
}
And in the template:
<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>
Method 2
If you're open to sending a property as part of the emitted event to determine whether to apply the class, do that from your Child Component and pass the updated stream
as the emitted data. This way, you won't need to manage the indexToAppendClassTo
list:
In Parent Component Class:
import { Component } from '@angular/core';
@Component({...})
export class AppComponent {
...
onSpeakEvent(event: any) {
// Method 2
const indexOfElement = this.streams.findIndex(strem => strem.name === event.name);
this.streams[indexOfElement] = { ...event };
}
}
In Parent Component Template:
<app-subscriber
*ngFor="let stream of streams"
[stream]="stream"
[session]="session"
(speakEvents)='onSpeakEvent($event)'
[ngClass]="stream.type === 'speaking' ? 'color': ''">
</app-subscriber>
And In Child Component Class:
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' });
}
...
}
And in Child Component Template:
<button (click)="onClick()">{{stream.name}}</button>
Here's a Working Sample StackBlitz with both approaches for reference.