Angular 16+ Signals vs Decorators: Understanding input(), output(), and signal()

Angular 16+ Signals vs Decorators Angular 16 introduced a new Composition API built around signals—a reactive primitive designed to make reactivity in Angular more powerful, predictable, and ergonomic. Along with this, Angular provided new functions: signal(), input(), and output() that offer a modern alternative to the classic @Input() and @Output() decorators. In this article, we’ll explore: What are signal(), input(), and output()? How do they compare with @Input() and @Output()? When should you use which? 1. The New Composition API import { signal, input, output } from '@angular/core'; These are functions, not decorators. They allow defining state and bindings in a more reactive and composable way. Example: @Component({ selector: 'user-card', standalone: true, template: `{{ name() }}` }) export class UserCardComponent { name = input.required(); onClick = output(); } Benefits: Strongly typed with required/optional inputs Fully signal-compatible Perfect for standalone and modern components 2. The Classic Decorator API import { Input, Output, EventEmitter } from '@angular/core'; These are decorators used since Angular 2 for parent-child communication. Example: @Component({ selector: 'user-card', standalone: true, template: `{{ name }}` }) export class UserCardComponent { @Input() name!: string; @Output() onClick = new EventEmitter(); } Benefits: Works with all Angular versions Compatible with modules and older codebases Side-by-Side Comparison Feature @Input() / @Output() input() / output() API Type Decorator Function Introduced In Angular 2 Angular 16 Reactive? No Yes (signals) Required Inputs Manual ! or guards input.required() Works with Signals Manual wrapping needed Native Event System EventEmitter Reactive callback via signals Recommended for Legacy apps, decorator style Modern apps with signals When to Use Each? Use Case Recommended API You’re using signals input() / output() You’re building modern apps input() / output() You’re working with legacy code @Input() / @Output() Using EventEmitter patterns @Output() Summary Angular’s evolution to signals is a major step forward in ergonomics and reactivity. If you’re starting a new Angular project or refactoring components to use the new standalone style, we highly recommend adopting input(), output(), and signal(). However, decorators like @Input() and @Output() remain powerful and necessary when working with older or module-based codebases. Both APIs can coexist, giving you the flexibility to migrate progressively.

Apr 21, 2025 - 01:36
 0
Angular 16+ Signals vs Decorators: Understanding input(), output(), and signal()

Angular Signals vs Decorators

Angular 16+ Signals vs Decorators

Angular 16 introduced a new Composition API built around signals—a reactive primitive designed to make reactivity in Angular more powerful, predictable, and ergonomic. Along with this, Angular provided new functions: signal(), input(), and output() that offer a modern alternative to the classic @Input() and @Output() decorators.

In this article, we’ll explore:

  • What are signal(), input(), and output()?
  • How do they compare with @Input() and @Output()?
  • When should you use which?

1. The New Composition API

import { signal, input, output } from '@angular/core';

These are functions, not decorators. They allow defining state and bindings in a more reactive and composable way.

Example:

@Component({
  selector: 'user-card',
  standalone: true,
  template: `

{{ name() }}` }) export class UserCardComponent { name = input.required<string>(); onClick = output<MouseEvent>(); }

Benefits:

  • Strongly typed with required/optional inputs
  • Fully signal-compatible
  • Perfect for standalone and modern components

2. The Classic Decorator API

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

These are decorators used since Angular 2 for parent-child communication.

Example:

@Component({
  selector: 'user-card',
  standalone: true,
  template: `

{{ name }}` }) export class UserCardComponent { @Input() name!: string; @Output() onClick = new EventEmitter<MouseEvent>(); }

Benefits:

  • Works with all Angular versions
  • Compatible with modules and older codebases

Side-by-Side Comparison

Feature @Input() / @Output() input() / output()
API Type Decorator Function
Introduced In Angular 2 Angular 16
Reactive? No Yes (signals)
Required Inputs Manual ! or guards input.required()
Works with Signals Manual wrapping needed Native
Event System EventEmitter Reactive callback via signals
Recommended for Legacy apps, decorator style Modern apps with signals

When to Use Each?

Use Case Recommended API
You’re using signals input() / output()
You’re building modern apps input() / output()
You’re working with legacy code @Input() / @Output()
Using EventEmitter patterns @Output()

Summary

Angular’s evolution to signals is a major step forward in ergonomics and reactivity. If you’re starting a new Angular project or refactoring components to use the new standalone style, we highly recommend adopting input(), output(), and signal().

However, decorators like @Input() and @Output() remain powerful and necessary when working with older or module-based codebases.

Both APIs can coexist, giving you the flexibility to migrate progressively.