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()
, andoutput()
? - 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.