Prefer Angular’s reactive signal patterns over manual subscription management and imperative approaches. Use signals directly in templates without calling getters, convert observables to signals with toSignal()
, and maintain reactive data flow throughout your application.
Key practices:
[(checked)]="mySignal"
not [(checked)]="mySignal()"
toSignal()
for reactive data that updates over timetoSignal(router.events.pipe(map(() => !!router.getCurrentNavigation())))
instead of manual subscription management for navigation stateExample of preferred reactive pattern:
@Component({
template: `
@if (loading()) {
<div>Loading...</div>
}
<div [class.admin]="isAdmin" [class.dense]="density() === 'high'">
`
})
export class MyComponent {
private route = inject(ActivatedRoute);
private router = inject(Router);
// Convert observable to signal for reactive updates
private data = toSignal(this.route.data);
user = computed(() => this.data()?.user as User);
// Use toSignal for navigation state
loading = toSignal(
this.router.events.pipe(
map(() => !!this.router.getCurrentNavigation())
),
{ initialValue: false }
);
// Direct signal usage in two-way binding
isAdmin = signal(false);
density = signal<'normal' | 'high'>('normal');
}
This approach provides better performance, cleaner code, and leverages Angular’s reactive primitives effectively.
Enter the URL of a public GitHub repository