DestroyRef is an injectable reference to the destruction lifecycle of the context where it is obtained. Register an onDestroy callback to run cleanup when that component or other injection context is destroyed, without placing the callback directly in ngOnDestroy. section 5.3.3
It makes lifecycle-aware reusable code practical. A search helper can inject DestroyRef, signal a private Subject during destruction, and return a debounced valueChanges observable that completes through takeUntil. Components using the helper no longer need their own destroy Subject or ngOnDestroy solely for that subscription. section 5.3.3 section 5.6
Listing 5.4 Reusable function for performing searches with time delay
import { DestroyRef, inject } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Subject } from 'rxjs';
import { debounceTime, takeUntil } from 'rxjs/operators';
export function createSearch<T>(control: FormControl<T>) {
const destroyRef = inject(DestroyRef);
const destroy$ = new Subject<void>();
destroyRef.onDestroy(() => destroy$.next());
return control.valueChanges.pipe(
debounceTime(500),
takeUntil(destroy$),
);
}
A reusable createSearch function injects DestroyRef, registers a destruction callback, and couples a debounced form-control stream to teardown. section 5.3.3
DestroyRef also underpins takeUntilDestroyed. The operator injects it when called in an injection context and completes the observable at context destruction. Outside such a context, inject DestroyRef where injection is valid and pass it explicitly to takeUntilDestroyed. section 5.3.4 section 5.3.4
When modernizing Subject-based teardown, use these checks:
- Replace destroy Subjects and takeUntil calls with takeUntilDestroyed where appropriate. section 5.3.4
- Remove ngOnDestroy only when it contains no unrelated cleanup logic. section 5.3.4
- Pass a DestroyRef explicitly when calling lifecycle-aware helpers or takeUntilDestroyed outside an injection context. section 5.3.4
Permission-driven employee form
An EditEmployeeComponent injects DestroyRef and passes it to takeUntilDestroyed from ngOnInit. The permission stream then stops automatically when the component is destroyed while it enables or disables form controls. section 5.3.4
