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?

0

There are 0 best solutions below