DEV Community

Cover image for The End of @Input() & @Output(): Angular 20’s Game-Changing Update
Mridu Dixit
Mridu Dixit

Posted on

The End of @Input() & @Output(): Angular 20’s Game-Changing Update

For years, Angular developers have relied on @Input() and @Output() decorators for parent-child communication. While powerful, they often added boilerplate and confusion, especially in larger apps.

With Angular 20, things are changing dramatically. 🎉
The framework now embraces native Signals and introduces the model() API for cleaner, more reactive state flow.

🔴 Why Move Away from @Input & @Output?

  • Too much ceremony: separate properties for input/output.
  • Easy to create spaghetti state flow in big projects.
  • Not aligned with Angular’s new reactive primitives (Signals).

🟢 Angular 20: Inputs & Outputs with Signals

Instead of using decorators, Angular 20 provides functions for defining component bindings:

  • input() → replaces @Input()
  • output() → replaces @Output()
  • model() → combines input + output into a single two-way binding

📝 Code Examples

🟢 Old Way (Angular 19 with @Input and @Output)

// child.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <p>{{ title }}</p>
    <button (click)="notify()">Notify Parent</button>
  `
})
export class ChildComponent {
  @Input() title!: string;
  @Output() notifyParent = new EventEmitter<string>();

  notify() {
    this.notifyParent.emit('Hello from Child!');
  }
}

Enter fullscreen mode Exit fullscreen mode
// parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <app-child
      [title]="parentTitle"
      (notifyParent)="onNotify($event)">
    </app-child>
  `
})
export class ParentComponent {
  parentTitle = 'Parent says Hi!';

  onNotify(msg: string) {
    console.log(msg);
  }
}

Enter fullscreen mode Exit fullscreen mode

🔵 New Way (Angular 20 with Signals)

// child.component.ts
import { Component, input, output } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <p>{{ title() }}</p>
    <button (click)="notify.emit('Hello from Child!')">Notify Parent</button>
  `
})
export class ChildComponent {
  title = input<string>();
  notify = output<string>();
}

Enter fullscreen mode Exit fullscreen mode
// parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <app-child
      [title]="parentTitle"
      (notify)="onNotify($event)">
    </app-child>
  `
})
export class ParentComponent {
  parentTitle = 'Parent says Hi!';

  onNotify(msg: string) {
    console.log(msg);
  }
}

Enter fullscreen mode Exit fullscreen mode

💡 Notice how much cleaner and signal-friendly this new API looks!

🟣Two-Way Binding with model()

The real game-changer is the model() API, which fuses input + output into a single signal.

// child.component.ts
import { Component, model } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <input [value]="title()" (input)="title.set($any($event.target).value)" />
    <p>You typed: {{ title() }}</p>
  `
})
export class ChildComponent {
  title = model<string>(''); // two-way bound
}

Enter fullscreen mode Exit fullscreen mode
// parent.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-parent',
  template: `
    <h2>Parent Component</h2>
    <app-child [(title)]="parentTitle"></app-child>
    <p>Parent Value: {{ parentTitle }}</p>
  `
})
export class ParentComponent {
  parentTitle = 'Hello World';
}

Enter fullscreen mode Exit fullscreen mode

💡 The model() API eliminates the need for separate @Input() and @Output(), giving us true two-way binding out of the box.

🌟 Why This Matters

  • 🚀 Less boilerplate, more readable code
  • 🔄 Seamless two-way binding with model()
  • ⚡ Reactive-first architecture, aligning with Angular Signals
  • 🧩 Better developer experience and performance

🏁 Conclusion

Angular 20 signals a major shift in how components talk to each other.
With input(), output(), and especially model(), we no longer need @Input() & @Output() decorators.

This isn’t just an API change—it’s a step toward a fully reactive Angular ecosystem.

👉 Stay tuned for more deep dives into Angular 20’s new features!

Top comments (0)