Angular app with a reactive form suddenly started reporting this error:
RuntimeError: NG0205: Injector has already been destroyed.
It probably comes from my async validator that uses observables.
import * as rx from 'rxjs';
class myComponent {
/** The form: select the filling device
*/
form = new FormGroup({
field: new FormControl<number>(0, {
asyncValidators: [
(control: AbstractControl): rx.Observable<ValidationErrors | null> =>
this.observable$.pipe(
rx.take(1), // complete observable immediately
//... validation ... //
),
]}),
});
In my particular case, a form with asyncValidators was to blame: Angular did not properly unsubscribe from a hot observable that used rxjs.share().
Use rx.takeUntil() to unsubscribe in time (thanks @ilya.chepurnoy):
import * as rx from 'rxjs';
class myComponent {
/** The form: select the filling device
*/
form = new FormGroup({
field: new FormControl<number>(0, {
asyncValidators: [
(control: AbstractControl): rx.Observable<ValidationErrors | null> =>
this.observable$.pipe(
rx.take(1), // complete observable immediately
//... validation ... //
rx.takeUntil(this.destroyed$), // the solution
),
]}),
});
// Observable that completes when the component is destroyed
private destroyed$: ReplaySubject<boolean> = new rx.ReplaySubject(1);
ngOnDestroy() {
this.destroyed$.next(true);
this.destroyed$.complete();
}
}
Alternatively, use untilDestroyed(this) from ngneat/until-destroy,
or the new takeUntilDestroyed()