I created a ComponentMessengerService
that uses an Event Emitter to allow for communication between two child components. The input
component is supposed to send information to the output
component via the use of an injected service in its constructor.
An Epic
is just a custom model I have made.
Component messenger service source code:
@Injectable({
providedIn: 'root'
})
export class ComponentMessengerService {
epicNumberUpdated = new EventEmitter<string>();
epicTitleUpdated = new EventEmitter<string>();
epicListUpdated = new EventEmitter<Epic[]>();
sendEpicNumber(epicNumber: string){
this.epicNumberUpdated.emit(epicNumber);
}
sendEpicTitle(epicTitle: string){
this.epicTitleUpdated.emit(epicTitle)
}
sendEpicList(epicList: Epic[]){
this.epicListUpdated.emit(epicList)
}
}
Output component source code:
export class OutputComponent implements OnInit {
public epicTitle: string;
public epicNumber: string;
public epicList: Epic[] = [];
constructor(private componentMessenger: ComponentMessengerService) {
this.subscribeAll();
}
subscribeAll(){
this.componentMessenger.epicListUpdated.subscribe(
(epicList: Epic[]) => {
this.epicList = epicList; })
this.componentMessenger.epicTitleUpdated.subscribe(
(epicTitle: string) => { this.epicTitle = epicTitle })
this.componentMessenger.epicNumberUpdated.subscribe(
(epicNumber: string) => {
this.epicNumber = epicNumber; })
}
}
The output's properties are data-bound to html elements and should be displayed once the component's properties have received the observables. I have debugged my application and can confirm that the input
component is indeed sending the observables. Unfortunately, when I tried adding console.log() statements within the subscribeAll()
to verify whether the event emitters were receiving any data, the line of code was never executed.
CodePudding user response:
did you try to call the subscribeAll() method in the ngOnInit ?
Difference between Constructor and ngOnInit
Update
I would solve the problem by using "Subject" instead of EventEmitter, I think EventEmitter need to work with @Output().
CodePudding user response:
We have Subject
and BehaviorSubject
for it.
@Injectable({
providedIn: 'root'
})
export class ComponentMessengerService {
epicNumberUpdated$ = new Subject<string>();
epicTitleUpdated$ = new Subject<string>();
epicListUpdated$ = new Subject<Epic[]>();
sendEpicNumber(epicNumber: string): void {
this.epicNumberUpdated$.next(epicNumber);
}
sendEpicTitle(epicTitle: string): void {
this.epicTitleUpdated$.next(epicTitle)
}
sendEpicList(epicList: Epic[]): void {
this.epicListUpdated$.next(epicList)
}
}
And don't forget about the unsubscription from Observables, because you can have a memory leak.
export class OutputComponent implements OnInit, OnDestroy {
epicTitle: string;
epicNumber: string;
epicList: Epic[] = [];
private unsubscribe$ = new Subject<void>();
constructor(private componentMessenger: ComponentMessengerService) {}
ngOnInit(): void {
initializeListeners();
}
ngOnDestroy(): void {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
private initializeListeners(): void {
this.componentMessenger.epicListUpdated$
.pipe(takeUntil(this.unsubscribe$))
.subscribe((epicList: Epic[]) => {
this.epicList = epicList;
});
this.componentMessenger.epicTitleUpdated$
.pipe(takeUntil(this.unsubscribe$))
.subscribe((epicTitle: string) => {
this.epicTitle = epicTitle;
});
this.componentMessenger.epicNumberUpdated$
.pipe(takeUntil(this.unsubscribe$))
.subscribe((epicNumber: string) => {
this.epicNumber = epicNumber;
});
}
}