13

Say there's ChildComponent which emits out an event called someEvent. Obviously, I can catch the event in ParentComponent declaring like, <child-component (someEvent)="onSomeEvent($event)"></child-component> and handle it with the method onSomeEvent in ParentComponent. But what I'm trying is that I want to handle the event with fromEvent operator in RxJS. I've tried fromEvent(this.childComponent.nativeElement, 'someEvent') after getting the ElementRef of the ChildComponent with @ViewChild. I discovered that the above approach works if the output EventEmitter's event name is the same as one of the native events such as click but it doesn't respond/work otherwise. Is there any ways to make it work with fromEvent?

DongBin Kim
  • 1,799
  • 5
  • 23
  • 43
  • Why do you want to use `fromEvent`? Are you trying to convert the Angular event into an observable? – cartant Mar 12 '18 at 04:21
  • @cartant Actually, using `fromEvent` is not that necessary but I'm trying to approach this way to handle the flow with rxjs operators – DongBin Kim Mar 12 '18 at 04:26
  • @cartant Would you mind reposting your answer? I was confused. It's still not working. – DongBin Kim Mar 12 '18 at 04:50
  • 1
    I've undeleted the answer. There are good reasons for avoiding direct access to native elements in Angular and for [not treating event emitters as observables](https://stackoverflow.com/questions/36076700/what-is-the-proper-use-of-an-eventemitter). – cartant Mar 12 '18 at 06:24
  • @cartant I think Accessing native elements directly in Angular is not bad unless I manipulate it. Why is it bad? – DongBin Kim Mar 13 '18 at 06:33
  • I find the original answer interresting: *I discovered that the above approach works if the output EventEmitter's event name is the same as one of the native events such as `click` but it doesn't work otherwise*. Is it possible to use `fromEvent(..,'customClick')` for custom events fired from `EventEmitter`? Lets say one directive on the same element fires `customClick` and second directive on the same element want to listen to such events. I solved it injecting one directive to the other and manually subscribe to `EventEmitter`, but I am curious why `fromEvent(..,'customClick')` doesn't work. – Felix Feb 22 '22 at 07:17

1 Answers1

15

If you want to convert the event into an observable, you could use a Subject, like this:

@Component({
  selector: 'parent-component',
  template: `
    <child-component (someEvent)="subject.next($event)">
    </child-component>
  `
})
export class ParentComponent {
  public subject = new Subject<any>();
  constructor() {
    this.subject.pipe(
      tap(event => console.log(event)) // or whatever
    ).subscribe();
  }
}

Doing so will provide you with an observable source - the subject - that emits whatever value the event emitter emits. From that you can compose whatever you want using RxJS operators.

cartant
  • 57,105
  • 17
  • 163
  • 197
  • So there will be no way to bind `Component` event(output EventEmitter) with `fromEvent` operator other than using `Subject`? With your suggestion, I would be able to use rxjs operators as I wanted but I would need to have seemingly extra `Subject` variable to accomplish what I want. – DongBin Kim Mar 12 '18 at 04:40
  • Even if you could, you shouldn't. cartant's solution is the correct one that you should use. – Ingo Bürk Mar 12 '18 at 07:05
  • @IngoBürk Apparently, I could directly subscribe to `someEvent`. Why should I have an extra Subject for this? – DongBin Kim Mar 13 '18 at 06:35
  • 2
    @DongBinKim Because `EventEmitter` [is not guaranteed to be implemented as an observable](https://stackoverflow.com/a/36076701/6680611). It's being an observable is an implementation detail. – cartant Mar 13 '18 at 07:26