How to use @Output decorator in Angular

Using the @Output decorator is essential for child-to-parent communication in Angular applications, enabling components to emit custom events and maintain loose coupling. As the creator of CoreUI, a widely used open-source UI library, I’ve designed thousands of Angular components using @Output decorators for button clicks, form submissions, and custom interactions in enterprise component libraries. From my expertise, the most effective approach is to use @Output decorator with EventEmitter and descriptive event names. This method provides type-safe event communication, clear component interfaces, and excellent developer experience while maintaining component reusability and testability.

Use @Output() decorator with EventEmitter to emit custom events from child components to parent components.

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

@Component({
  selector: 'app-user-card',
  template: `
    <div class="user-card">
      <h3>{{ user.name }}</h3>
      <p>{{ user.email }}</p>
      <button (click)="onEdit()" class="btn-edit">Edit</button>
      <button (click)="onDelete()" class="btn-delete">Delete</button>
      <button (click)="onStatusChange()" class="btn-status">
        {{ user.active ? 'Deactivate' : 'Activate' }}
      </button>
    </div>
  `
})
export class UserCardComponent {
  @Input() user: any

  @Output() edit = new EventEmitter<any>()
  @Output() delete = new EventEmitter<number>()
  @Output() statusChange = new EventEmitter<{id: number, active: boolean}>()

  onEdit() {
    this.edit.emit(this.user)
  }

  onDelete() {
    this.delete.emit(this.user.id)
  }

  onStatusChange() {
    this.statusChange.emit({
      id: this.user.id,
      active: !this.user.active
    })
  }
}

// Parent component template:
// <app-user-card
//   [user]="selectedUser"
//   (edit)="handleEdit($event)"
//   (delete)="handleDelete($event)"
//   (statusChange)="handleStatusChange($event)">
// </app-user-card>

The @Output() decorator marks properties as event emitters that can send data to parent components. Use EventEmitter<T> with TypeScript generics to specify the event payload type. Call emit() method to send events with optional data payload. Parent components listen to custom events using event binding syntax (eventName)="handler($event)". The $event contains the emitted data. This creates a clean separation between child component logic and parent component handling.

Best Practice Note:

This is the same approach we use in CoreUI Angular components for consistent event-driven architecture and component communication. Use descriptive event names, type the EventEmitter with specific payload types, emit meaningful data objects rather than primitive values, and always declare outputs for better component documentation and IDE support.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author