← Back to Articles         
Two way communication between parent and child

Two way communication between parent and child

Published on 29 Sep 2026     2 min read Angular
Angular Components

Yes — you mean Angular’s two-way binding convention, where @Input() + matching @Output() together behave like a model:

@Input()  value
@Output() valueChange

Together → [(value)]

Full Simple Example

1. Child Component

counter.ts

import {
  Component,
  Input,
  Output,
  EventEmitter
} from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  templateUrl: './counter.html'
})
export class Counter {

  @Input()
  count: number = 0;

  @Output()
  countChange = new EventEmitter<number>();

  increment() {
    this.count++;

    this.countChange.emit(this.count);
  }

  decrement() {
    this.count--;

    this.countChange.emit(this.count);
  }
}

counter.html

<h3>Child Component</h3>

<p>Count: {{ count }}</p>

<button (click)="increment()">+</button>

<button (click)="decrement()">-</button>

2. Parent Component

app.ts

import { Component } from '@angular/core';
import { Counter } from './counter/counter';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [Counter],
  templateUrl: './app.html'
})
export class App {

  count = 10;
}

app.html

<h2>Parent Component</h2>

<p>Parent Count: {{ count }}</p>

<app-counter [(count)]="count"></app-counter>

How [(count)] Works

This:

<app-counter [(count)]="count"></app-counter>

is shorthand for:

<app-counter
  [count]="count"
  (countChange)="count = $event">
</app-counter>

Angular recognizes the naming convention:

@Input()
count: number = 0;

@Output()
countChange = new EventEmitter<number>();

The output must be named <inputName>Change.

count       → @Input()
countChange → @Output()

Therefore:

[(count)]

Communication Flow

Parent
count = 10
   |
   | [count]
   ↓
Child
count = 10
   |
User clicks +
   |
countChange.emit(11)
   |
   | (countChange)
   ↓
Parent
count = 11

So data can move in both directions:

Parent ──@Input()──→ Child
Parent ←─@Output()── Child

Modern Angular: model()

This is exactly what Angular's newer model() API simplifies.

Instead of:

@Input()
count = 0;

@Output()
countChange = new EventEmitter<number>();

you can write:

count = model(0);

Child:

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

@Component({
  selector: 'app-counter',
  standalone: true,
  templateUrl: './counter.html'
})
export class Counter {

  count = model(0);

  increment() {
    this.count.update(value => value + 1);
  }

  decrement() {
    this.count.update(value => value - 1);
  }
}

Parent remains:

<app-counter [(count)]="count"></app-counter>

Interview Key Point

model() provides two-way binding between parent and child. It is the modern alternative to manually creating an @Input() and a corresponding <name>Change @Output().

Traditional:

@Input() count
        +
@Output() countChange
        ↓
   [(count)]


Modern:

model()
   ↓
[(count)]
← Back to Articles