Why takeUntilDestroyed(this.destroyRef) in registerOnChange of a ControlValueAccessor...

Discussão em 'Angular' iniciado por Alexandre SIRKO, Fevereiro 7, 2025.

  1. 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?

    Continue reading...

Compartilhe esta Página