
Quick answer: Angular component interaction runs in two directions. Data flows down through input(), and events flow up through output(). To reach a child that is already rendered, use a viewChild query. For content passed into a component from its host, use contentChild. Inputs down, outputs up is the rule that keeps a component tree predictable.The sections below cover Angular component interaction in both directions: inputs down, outputs up, then viewChild and contentChild for the cases where the tree is not enough — and when Angular component interaction should move into a shared service instead.
Table of Contents
Passing data down with input
An input is a value the parent sets on the child. The modern signal form uses the input() function, which makes the value reactive and read-only inside the child.
import { Component, input } from '@angular/core';
@Component({
selector: 'app-stars',
template: `<span>{{ rating() }} / 5</span>`,
})
export class StarsComponent {
rating = input.required<number>();
label = input('Rating');
}The parent binds it the same way it binds any property: <app-stars [rating]="product.stars" />. Note the single brackets — this is the property binding from the previous article. input.required makes the value mandatory, so forgetting to pass it is a compile error.
Sending events up: Angular component interaction with output
When something happens inside a child and the parent needs to know, the child emits an output. The parent then handles it like a DOM event.
import { Component, output } from '@angular/core';
@Component({
selector: 'app-rating-input',
template: `<button (click)="choose(4)">4 stars</button>`,
})
export class RatingInputComponent {
rated = output<number>();
protected choose(value: number) {
this.rated.emit(value);
}
}The parent listens with parentheses, the same syntax as a click handler:
<app-rating-input (rated)="saveRating($event)" />$event carries whatever the child emitted — here, the number of stars. Inputs carrying data down and outputs carrying events up is the whole contract between a parent and child.
Reading a child with viewChild
Sometimes the parent needs to call a method on the child directly, or read a value from it. A view query gives you a reference to the child instance.
import { Component, viewChild, AfterViewInit } from '@angular/core';
import { ChartComponent } from './chart.component';
@Component({
selector: 'app-report',
imports: [ChartComponent],
template: `<app-chart />`,
})
export class ReportComponent implements AfterViewInit {
chart = viewChild.required(ChartComponent);
ngAfterViewInit() {
this.chart().render();
}
}The child exists only after the view renders, so the first safe moment to use the reference is ngAfterViewInit. Calling into a child this way is a useful escape hatch, but prefer inputs and outputs where you can — they are easier to trace.
Receiving markup with contentChild
Content projection is for wrapping. A card component wants to accept whatever the parent puts between its tags, and sometimes inspect that content if it is another component.
@Component({
selector: 'app-panel',
template: `
<section class="panel">
<ng-content />
</section>
`,
})
export class PanelComponent {}The parent then writes <app-panel><p>Anything here.</p></app-panel>, and <ng-content /> marks where that markup appears. Use contentChild when the wrapped content is a specific component and the panel needs to read from it.
Angular component interaction: choosing the right mechanism
| Direction | Tool | Use when |
|---|---|---|
| Parent to child | input() | The child needs a value from above |
| Child to parent | output() | The child reports an event upward |
| Parent reaches child | viewChild | You must call a method on a rendered child |
| Component inspects projected content | contentChild | Wrapping another component |
If two distant components must share state, do not thread inputs through five layers. Put the state in a service and inject it into both — see services and dependency injection, or the shared-state patterns in signals and state management.
Prefer learning component patterns on a real project? Ampersand Academy teaches Angular one-to-one, from components to deployed apps.
Frequently asked questions
What is the difference between input and output in Angular?
An input passes data down from a parent to a child. An output emits an event up from a child to its parent. Together they define the contract between the two components.
Is @Input decorator still used in Angular?
It works, but the signal based input function is the modern approach. It returns a reactive value and supports input.required for mandatory inputs.
When can I use a viewChild reference?
Only after the child view has rendered, which is in ngAfterViewInit. The reference is not available in ngOnInit because the child does not exist yet.
Should I use ng-content or an input for child content?
Use ng-content to project markup a parent places between the component tags. Use an input when the parent passes a value or data object the component renders itself.
How do I share state between unrelated components?
Put the state in a shared service and inject it into each component, rather than passing inputs through many layers. A signal in a service updates every consumer automatically.
Last updated on · Written by Dinesh Kumar R

