
Не секрет, что у новичков в Angular могут возникнуть проблемы с передачей данных между компонентами, потому что не всегда удается использовать Input и Output декораторы. Предлагаю вашему вниманию реализацию паттерна EventEmitter на Angular.
Для начала определим наш EventEmitter сервис, где разместим наш eventEmitterSubject$, принимающий поле action(тип события) и не обязательное поле payload(данные, которые мы хотим передать), для передачи событий и подписки на них.
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
export type Actions = 'CREATE' | 'DELETE' | 'UPDATE';
@Injectable({
providedIn: 'root'
})
export class EventEmitterService {
eventEmitterSubject$ = new Subject<{ action: Actions, payload?: any }>();
}
Теперь можно определить и дочерний компонент, который будет вызывать события у родительского, через наш EventEmitter сервис, а конкретно вызывать метод next, у eventEmitterSubject$.
export class ChildComponent {
constructor(private eventService: EventEmitterService) { }
onCreate(data) {
this.eventService
.eventEmitterSubject$.next({action: 'CREATE', payload: data});
}
onDelete(id) {
this.eventService
.eventEmitterSubject$.next({action: 'DELETE', payload: { id }});
}
}
И наконец, на эти события можно подписаться в родительском компоненте.
Обратите внимание, что можно подписываться, как на все события, так и на конкретные с помощью оператора filter, также надо не забыть отписатся от подписки при дестроее компонента, чтобы не было утечек памяти.
export class AppComponent implements OnInit, OnDestroy {
// не забываем отписываться
destroy$ = new Subject();
constructor(private eventEmitterService: EventEmitterService) {}
ngOnInit(): void {
// подписка на все события
this.eventEmitterService.eventEmitterSubject$
.pipe(takeUntil(this.destroy$))
.subscribe((event) => {
switch (event.action) {
case 'CREATE': {
// do something
break;
}
case 'DELETE': {
// do something
break;
}
}
});
// подписка на конкретное событие
this.eventEmitterService.eventEmitterSubject$.pipe(
takeUntil(this.destroy$),
filter(event => event.action === 'CREATE')
).subscribe(({payload}) => {
// do something
});
}
ngOnDestroy() {
// отписка
this.destroy$.next();
this.destroy$.complete();
}
}
Надеюсь эта статься поможет начинающим разработчикам лучше понять, как могут взаимодействовать компоненты между собой с использованием cервисов и rxjs.