AcademyAngular
Event Binding and Custom Outputs
(event)="handler($event)" binds a native DOM event; @Output() lets a component emit its own, typed the same way any other value in the app is typed.
2 min readUpdated 3 exercises
Parentheses bind an event; $event is whatever it carries
(event)="expression" wires a native DOM event to a template expression, and $event inside that expression is the event object the browser fired — a KeyboardEvent, a MouseEvent, whatever the event name implies:
<form (submit)="onSubmit($event)">
<input (keydown.enter)="addTodo($event)" />
</form>A form that reloads the page on Enter is almost always this: the handler runs, but nothing called $event.preventDefault() first, so the browser's default submit-and-navigate behavior fires right alongside the component's own logic. The fix is never "stop using (submit)" — it is calling preventDefault() as the first line of the handler, the same instinct as in any framework-free DOM code.
@Output() makes a component's own events, typed
A child component emits upward through an @Output() property, conventionally an EventEmitter:
@Output() rate = new EventEmitter<number>();
onStarClick(value: number): void {
this.rate.emit(value);
}<app-star-rating (rate)="onRate($event)" /> in the parent then receives whatever the child .emit()s as its own $event — the mechanism is identical to a native DOM event, which is precisely the point: @Output() exists to make a custom event indistinguishable, from the template's perspective, from click or submit.
A typed union output has to emit every branch it declares
Once an output's generic is a union — EventEmitter<{ status: 'success' } | { status: 'error'; message: string }> — TypeScript will happily let a handler compile while only ever emitting the success branch; nothing forces every code path that can fail to actually call .emit() with the error shape. That gap does not show up as a type error, because the emitter's declared type is correct — only its call sites are incomplete, and finding that requires reading what triggers the failure path, not just what the type declares.
What interviewers check
Whether you reach for $event.preventDefault() before you reach for a workaround, and whether you can explain @Output()/EventEmitter as "the same idea as a native DOM event, just declared by application code" rather than as a separate mechanism to memorize.
Now practice it
1 quiz · 2 drillsReading this page is the cheap half. These are the exercises that make you use it.
- Event HandlingFix a todo form that reloads the page on Enter, and a delete button that reopens the very item it just removed.DrillSolve · EasyDrillSolve · Easy
- Typed @Output() with a Result-shaped EventProFix a save button whose typed success/error @Output() never actually emits the error branch, even when saving fails.DrillSolve · HardDrillSolve · Hard
- Components & Directives · Component BasicsComponent fundamentals questions that cover @Output() alongside the rest of the component API surface.QuizTake · EasyQuizTake · Easy
Read next
Control Flow: @if and @for
Angular 17+ replaced *ngIf and *ngFor with built-in @if and @for blocks — faster, stricter about tracking, and no CommonModule import required.
2 min
Signals: signal(), computed() and effect()
signal() holds a value behind a getter/setter pair; computed() derives from it lazily; effect() reacts to it. Angular's answer to Vue's ref or a React hook.
2 min