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:

Example 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.