tezvyn:

Angular @Output(): Child Components Reporting Up

AI-drafted, machine-checkedSource: angular.devbeginner
Angular @Output(): Child Components Reporting Up

An @Output() lets a child component tell its parent something happened, using an EventEmitter. It’s the standard way to handle events like button clicks that the parent needs to act on. The footgun is forgetting to actually `.emit()` the event.

WHY IT EXISTS: Angular's component architecture promotes encapsulation, where components are self-contained units. By default, data flows down from parent to child via @Input(). This creates a predictable data flow but raises a question: how does a child communicate back up to its parent? @Output() exists to solve this, providing a clean, one-way channel for events to flow upwards without breaking encapsulation.

THE MENTAL MODEL: Think of @Output() as installing a doorbell on a child component's "house". The child component itself decides when to ring that bell by calling the .emit() method. The parent component, which placed the child component, listens for the ring. The parent decides what to do when it hears the bell, but the child doesn't know or care. It just announces that something happened.

HOW IT WORKS: In the child component, you declare a property and decorate it with @Output(). This property must be a new instance of EventEmitter. For example: @Output() somethingHappened = new EventEmitter<string>();. When an event occurs in the child, like a button click, you call this.somethingHappened.emit('some data'). In the parent component's template, you bind to this event using parentheses: <app-child (somethingHappened)="parentMethod(event)"></app-child>. The event variable contains the data that was emitted.

WHEN TO USE IT: Use @Output() for any communication from a child to its immediate parent. This is the canonical pattern for handling user interactions within a child component that the parent needs to be aware of. Examples include a "delete" button in a list item, a "submit" event from a custom form control, or a "close" action on a modal dialog.

WHEN NOT TO USE IT: Avoid using @Output() for communicating between distant or unrelated components. Chaining events up multiple levels of the component tree is cumbersome and creates tight coupling. For cross-component communication, a shared service with an RxJS Subject or a state management library is a better solution. Also, never use @Output() to pass data down to a child; that is the specific job of @Input().

ONE CANONICAL EXAMPLE: A child component, TodoItemComponent, displays a single todo and has a "complete" button. It defines @Output() complete = new EventEmitter<number>();. When its button is clicked, it calls this.complete.emit(this.todo.id). The parent TodoListComponent uses it in a loop: <app-todo-item *ngFor="let todo of todos" [todo]="todo" (complete)="markAsComplete($event)"></app-todo-item>. The parent's markAsComplete method then receives the ID of the completed todo.

Read the original → angular.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.