Lesson 10 / 30

@Input() & @Output()

Pass data down to a child and events back up to a parent.

Decorator style

@Input() receives a value from the parent template; @Output() with an EventEmitter sends events up.

@Component({ selector: 'app-star-rating', standalone: true, template: `...` })
export class StarRatingComponent {
  @Input() rating = 0;
  @Output() ratingChange = new EventEmitter<number>();

  select(value: number) {
    this.ratingChange.emit(value);
  }
}

Signal-based input()/output()

Newer Angular offers input() and output() functions — signal-friendly, and input.required() enforces a value is always passed.

import { Component, input, output } from '@angular/core';

@Component({ selector: 'app-star-rating', standalone: true, template: `...` })
export class StarRatingComponent {
  rating = input.required<number>();
  ratingChange = output<number>();

  select(value: number) {
    this.ratingChange.emit(value);
  }
}

Using it from a parent

The parent binds the input as a property and listens to the output as an event, just like a native element.

<app-star-rating [rating]="product.rating" (ratingChange)="onRate($event)" />

Quick check: Which function guarantees a parent must always pass a value?

  • input()
  • input.required()
  • output()
Answer

input.required() — `input.required()` makes the compiler enforce that the parent always binds a value.