Angular Icon Get 73% off the Angular Master bundle

See the bundle then add to cart and your discount is applied.

0 days
00 hours
00 mins
00 secs

Write Angular like a pro. Angular Icon

Follow the ultimate Angular roadmap.

Component events with EventEmitter and @​Output in Angular

Angular components are the fundamental building blocks of application architecture, when paired with a one-way dataflow practice.

In this post we’re going to explore how to use Angular components correctly with EventEmitter and the @Output decorator to achieve the desired architecture and communication.

This is typically done via “events”, hence our “EventEmitter” and is designed around a uni-directional data flow system that adopts a much more reasonable approach to application development.

Let’s finalise the basics of parent-child and child-parent communication by introducing EventEmitter and @Output.

This tutorial will cover stateless component events using the EventEmitter API and @Output decorator. These allow us to emit change or any custom event names from a custom component in Angular.

This post follows from the previous article on passing data in Angular components with @Input, so be sure to read that first!

Stateful (parent) component binding

Much like in the previous tutorial, where we setup an @Input decorator to accept an input binding, we can do the same and listen in the parent for when a value changes inside our child component.

To do this, we’ll head back to our parent component that’s rendering out our count:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <div class="app">
      Parent: {{ myCount }}
      <counter
        [count]="myCount"
        (change)="countChange($event)">
      </counter>
    </div>
  `
})
export class AppComponent {
  myCount: number = 10;
  countChange(event) {

  }
}

I’ve made a few additions here:

Angular Directives In-Depth eBook Cover

Free eBook

Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.

  • Green Tick Icon Observables and Async Pipe
  • Green Tick Icon Identity Checking and Performance
  • Green Tick Icon Web Components <ng-template> syntax
  • Green Tick Icon <ng-container> and Observable Composition
  • Green Tick Icon Advanced Rendering Patterns
  • Green Tick Icon Setters and Getters for Styles and Class Bindings

This sets up our finalised uni-directional dataflow. The data flows down from the AppComponent class, into the ``, the counter can then change the values - and once the value has changed we expect countChange() to be called. We now need to wire this up.

@Output decorator

Much like using Input, we can import Output and decorate a new change property inside our CounterComponent:

import { Component, Input, Output } from '@angular/core';

@Component({...})
export class CounterComponent {

  @Input()
  count: number = 0;

  @Output()
  change;

  // ...

}

This will configure the metadata necessary to tell Angular this property is to be treated as an output binding. However, it needs to sit alongside something called the EventEmitter.

EventEmitter

This is the interesting part. To be able to use our Output, we need to import and bind a new instance of the EventEmitter to it:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({...})
export class CounterComponent {

  // ...

  @Output()
  change = new EventEmitter();

  // ...

}

Using TypeScript to the fullest we’d do something like this to signify the type of event value we are emitting, and our change output is of type EventEmitter. In our case we are emitting a number type:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({...})
export class CounterComponent {

  // ...

  @Output()
  change: EventEmitter<number> = new EventEmitter<number>();

  // ...

}

Invoking the EventEmitter

So what’s happening here? We’ve created a change property, and bound a new instance of EventEmitter to it - what next?

We can simply call our this.change method - however because it references an instance of EventEmitter, we have to call .emit() to emit an event to the parent:

@Component({...})
export class CounterComponent {

  @Input()
  count: number = 0;

  @Output()
  change: EventEmitter<number> = new EventEmitter<number>();

  increment() {
    this.count++;
    this.change.emit(this.count);
  }

  decrement() {
    this.count--;
    this.change.emit(this.count);
  }

}

This will then emit a change to our (change) listener we setup in the parent, to which our countChange($event) callback will be invoked, and the data associated with the event will be given to us via the $event property.

Stateful callback assignment

Here’s what we’ll need to do, re-assign this.myCount with the event that’s passed back. I’ll explain why below:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <div class="app">
      Parent: {{ myCount }}
      <counter
        [count]="myCount"
        (change)="countChange($event)">
      </counter>
    </div>
  `
})
export class AppComponent {
  myCount: number = 10;
  countChange(event) {
    this.myCount = event;
  }
}

This creates a pure uni-directional dataflow. The data comes from AppComponent, flows into our counter, the counter makes a change, and emits that change back to the parent on our command - via the EventEmitter we setup. Once we’ve got that data back up, we merge those changes back into our parent (stateful) component.

The reason we’re doing this is to demonstrate that Parent: {{ myCount }} updates at the same time our Output informs the parent.

Bonus: custom property names

Much like we learned with @Input() and creating custom property names, we can also do the same with @Output().

Let’s assume that we change the (change) binding to (update):

@Component({
  selector: 'app-root',
  template: `
    <div class="app">
      Parent: {{ myCount }}
      <counter
        [count]="myCount"
        (update)="countChange($event)">
      </counter>
    </div>
  `
})
export class AppComponent {
  myCount: number = 10;
  countChange(event) {
    this.myCount = event;
  }
}

We can hook up our custom property name, whilst preserving the internal @Output property name:

@Component({...})
export class CounterComponent {

  // ...

  @Output('update')
  change: EventEmitter<number> = new EventEmitter<number>();

  increment() {
    this.count++;
    this.change.emit(this.count);
  }

  decrement() {
    this.count--;
    this.change.emit(this.count);
  }

}

Essentially, we’re just telling Angular here to lookup update as the property to be bound to, and we can continue using this.change internally.

So there you have it, the guide to using Outputs with EventEmitter in Angular’s components. Now you understand the model, happy coding!

To learn more techniques, best practices and real-world expert knowledge I’d highly recommend checking out my Angular courses - they will guide you through your journey to mastering Angular to the fullest!

Learn Angular the right way.

The most complete guide to learning Angular ever built.
Trusted by 82,951 students.

Todd Motto

with Todd Motto

Google Developer Expert icon Google Developer Expert

Related blogs 🚀

Free eBooks:

Angular Directives In-Depth eBook Cover

JavaScript Array Methods eBook Cover

NestJS Build a RESTful CRUD API eBook Cover