angulartypescriptobservableeventemitterbehaviorsubject

Why using EventEmitter in angular is considered bad practice


In an angular project (v17), I've used EventEmitter to notify one component, of the changes of another, somewhat unrelated (not a parent nor grandparent, not a child nor a grandchild) component. I can't put the exact code here (because of NDA) but this is a close enough example.

Here is the service, just an EventEmitter:

@Injectable({ providedIn: 'root' })
export class EventService {

  public eventEmitter: EventEmitter<SomeModel> = new EventEmitter<SomeModel>();
}

This is the component that fires the event:

@Component({
  standalone: true,
})
export class SomeComponent {

  eventService = inject(EventService);

  onEmitEvent() {
    this.eventService.eventEmitter.emit(this.someObject);
  }
}

And this is where I'm listening for the event:

@Component({
  standalone: true,
})
export class SomeOtherComponent {

  anArray: SomeModel[] = [];

  eventService = inject(EventService);

  constructor() {
    this.eventService.eventEmitter.subscribe((inputObject: SomeModel) => {
      if (/*anArray does not have inputObject*/) {
        this.anArray.push(inputObject);
      }
    });
  }
}

This works fine, however one of my colleagues reviewed the code and recommended using Observable, or better, BehaviorSubject instead. I've searched in the documents and in stack for a little while and while I did find questions with answers that would also recommend against using EventEmitter (like This one), I couldn't find something that would tell me why I should not use EventEmitter.

For the thing that I wanted to do, I think using the EventEmitter is making the code very simple and arguably, more understandable. There are multiple instances of the emitter component but they are not nested, and the emitting only happens when the user clicks on the component, so at most only one event is being emitted at a given time. There is only one component that receives the events and there isn't any complex logic, so the event is handled pretty quickly.

Is using EventEmitter even a bad practice? If yes, then why? Using other methods that I did find makes this simple code way more complex than it needs, so unless there is a good reason for it, I prefer sticking with the EventEmitter instead. Thanks :)


Solution

  • Event Emitter extends/ inherits a subject along with extra angular features like using destroyRef useful when unsubscribing the emitter subscriptions, looking at the source code event_emitter.ts.

    The reason they are recommending Subject and BehaviorSubject might be that it is designed for data communication between two unrelated components.

    But the EventEmitter can do both data communication and be integrated with @Output for sending data from child to parent.

    You can do it, but the basic requirement can be fulfilled by just a Subject or BehaviorSubject.