I have this simple ControlValueAccessor component:
@Component({
selector: 'app-my-input',
standalone: true,
imports: [...],
templateUrl: './my-input.component.html',
styleUrls: ['./my-input.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: MyInputComponent, multi: true }],
})
export class MyInputComponent implements ControlValueAccessor {
private readonly destroyRef = inject(DestroyRef);
readonly ctrl = new FormControl<string[]>([]);
registerOnChange(fn: (value: string[]) => void): void {
this.ctrl.valueChanges
.pipe(
takeUntilDestroyed(this.destroyRef),
map(arr => (arr.length ? arr : null)),
)
.subscribe(fn);
}
registerOnTouched(): void {
// nothing to do
}
writeValue(uuidsSelected: string[]): void {
this.ctrl.setValue(uuidsSelected);
}
}
When the component is destroy, I got the error: View has already been destroyed.
If I replace the register function by:
onChange: (value: string[]) => void = noop;
ngOnInit(): void {
this.ctrl.valueChanges
.pipe(
takeUntilDestroyed(this.destroyRef), // can not use untilDestroyed in registerOnChange
map(arr => (arr?.length ? arr : null)),
)
.subscribe(v => this.onChange(v));
}
registerOnChange(fn: (value: string[]) => void): void {
this.onChange = fn;
}
It work without error.
Does any one have an explanation?
Why takeUntilDestroyed(this.destroyRef)
inside a registerOnChange
generate an error and not inside a ngOnInit
?