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.

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

DirectionToolUse when
Parent to childinput()The child needs a value from above
Child to parentoutput()The child reports an event upward
Parent reaches childviewChildYou must call a method on a rendered child
Component inspects projected contentcontentChildWrapping 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