codejump

AcademyAngular

Input, Output and Content Projection

@Input()/@Output() pass data down and events up between components; <ng-content> lets a parent's markup render inside a child it doesn't control.

2 min readUpdated

3 exercises

Waiting at the end of this page.

The decorator is what makes a field an @Input(), not the name

@Input() and @Output() are property decorators — the parent-to-child, child-to-parent wiring only exists because the decorator registers the field with Angular's binding system, not because a field happens to be named rating:

typescript
@Input() rating = 0;
@Output() rated = new EventEmitter<number>();

A star-rating child that "ignores the parent's rating" is frequently a field that is bound correctly in the parent's template — [rating]="value" — but never actually decorated with @Input() in the child, so Angular has no idea that binding exists and the assignment silently goes nowhere. The inverse breaks the same way: a click that never reports back up is an EventEmitter field with no @Output(), so .emit() runs and nothing outside the component is listening for it.

<ng-content> projects whatever the parent put between the tags

A component's own template can render its caller's markup, unmodified, wherever <ng-content> appears:

HTML
<!-- card.component.html -->
<div class="card">
  <ng-content></ng-content>
  <ng-content select="[footer]"></ng-content>
</div>

<ng-content> with no select catches the default, unlabeled content; <ng-content select="[footer]"> catches only content marked with a matching attribute, e.g. <div footer>...</div> in the caller. A card that ignores everything the parent puts inside it is missing the plain <ng-content> slot entirely; a card that renders the body but drops the footer usually has a select string that does not match what the caller actually wrote — select="footer" looking for an element name when the caller used an attribute, or vice versa.

Projection is structural, not a copy

Content projected through <ng-content> is still the parent's own template, evaluated in the parent's context — a projected {{ }} expression reads the parent's fields, not the child's, even though it visually renders inside the child's DOM. That is the detail that trips up anyone assuming <ng-content> works like a prop being copied in: it is closer to a hole in the child's layout that the parent's own content is dropped into, still belonging to the parent.

What interviewers check

Whether you can point at the exact decorator that turns a plain field into a binding, and whether you understand <ng-content select="..."> well enough to debug "why did my slot not catch anything" rather than just copying the selector syntax from an example.

Now practice it

1 quiz · 2 drills

Reading this page is the cheap half. These are the exercises that make you use it.