Repository: angular
Issue: Calling ChangeDetectorRef.detectChanges in child view causes error in parent NgForOf directive
Labels: area: core,core: change detection,core: differs,P4

### Which @angular/* package(s) are the source of the bug?

core, forms

### Is this a regression?

No

### Description

TL;DR: When a child view calls `ChangeDetectorRef.detectChanges` at an appropriate moment in its creation lifecycle, it can cause `ngForOf` to throw an error when deleting that child in response to input binding changes. The nature of the connection between these two events is mysterious to me.

Longer explanation:
I have an `ngForOf` directive that operates over a list of `FormControl` elements, and produces a `<list-item>` view for every one. `ListItem` implements the `ControlValueAccessor` interface, and every `ListItem` is hooked up to its associated `FormControl` element. I have button that, when clicked, deletes one of the `FormControl` elements, and thus causes `ngForOf` to update, removing that control's associated view. It looks like this:

```
@Component({
  selector: 'my-app',
  template: `
<ul>
  <list-item 
    *ngFor="let control of controls"
    [formControl]="control"
    (registerOnChangeCalled)="changeDetectorRef.detectChanges()"
    ></list-item>
</ul>
<button (click)="controls.splice(0, 1)">remove first list item</button>`,
})
export class AppComponent {
  controls = [new FormControl(), new FormControl()];

  constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
}
```
Note that a `registerOnChangeCalled` event fired from a `<list-Item>` causes `changeDetectorRef.detectChanges()` to be called.

My `ListItem` component is very simple:
```
@Component({
  selector: 'list-item',
  template: `<li>I am list item</li>`,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ListItem),
      multi: true,
    },
  ],
})
export class ListItem implements ControlValueAccessor {
  constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
  @Output() registerOnChangeCalled = new EventEmitter();

  registerOnChange(updateModelValue) {
    this.registerOnChangeCalled.emit(null);
  }

  writeValue(modelValue) { /* unimplemented */ }
  registerOnTouched() { /* unimplemented */ }
}
```

In this minimal repro example, `registerOnChange` only emits an event to `registerOnChangeCalled`, although in a real app it would do more. `registerOnChange` is a `ControlValueAccessor` method which is called once during the `FormControl` directive initialization,  after `ListItem`'s `ngOnInit` and before its `ngAfterContentInit`.

With this setup, clicking the `AppComponent` button causes the following error to be thrown:
```
ERROR TypeError: Cannot read properties of null (reading 'destroyed')
    at ViewContainerRef_.move (refs.ts:218:17)
    at eval (ng_for_of.ts:244:33)
    at DefaultIterableDiffer.forEachOperation (default_iterable_differ.ts:112:9)
    at NgForOf._applyChanges (ng_for_of.ts:227:13)
    at NgForOf.ngDoCheck (ng_for_of.ts:221:25)
    at checkAndUpdateDirectiveInline (provider.ts:220:15)
    at checkAndUpdateNodeInline (view.ts:442:14)
    at checkAndUpdateNode (view.ts:402:12)
    at debugCheckAndUpdateNode (services.ts:435:44)
    at debugCheckDirectivesFn (services.ts:396:7)
```

If I do not call `changeDetectorRef.detectChanges()`, the error will not be thrown. If I call `changeDetectorRef.detectChanges()` in `ListItem.ngOnInit` or `ngAfterContentInit`, the error will not be thrown.

This is effectively a repro of https://github.com/angular/angular/issues/45417, which was closed 12 days ago due to a failure to repro.

### Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/angular-yjdjfe?file=src/app/app.component.ts

### Please provide the exception or error you saw

```true
ERROR TypeError: Cannot read properties of null (reading 'destroyed')
    at ViewContainerRef_.move (refs.ts:218:17)
    at eval (ng_for_of.ts:244:33)
    at DefaultIterableDiffer.forEachOperation (default_iterable_differ.ts:112:9)
    at NgForOf._applyChanges (ng_for_of.ts:227:13)
    at NgForOf.ngDoCheck (ng_for_of.ts:221:25)
    at checkAndUpdateDirectiveInline (provider.ts:220:15)
    at checkAndUpdateNodeInline (view.ts:442:14)
    at checkAndUpdateNode (view.ts:402:12)
    at debugCheckAndUpdateNode (services.ts:435:44)
    at debugCheckDirectivesFn (services.ts:396:7)
```


### Please provide the environment you discovered this bug in (run `ng version`)

```true
"dependencies": {
    "@angular/animations": "^12.1.0",
    "@angular/common": "^12.1.0",
    "@angular/compiler": "^12.1.0",
    "@angular/core": "^12.1.0",
    "@angular/forms": "^12.1.0",
    "@angular/platform-browser": "^12.1.0",
    "@angular/platform-browser-dynamic": "^12.1.0",
    "@angular/router": "^12.1.0",
    "core-js": "^3.15.1",
    "rxjs": "^7.1.0",
    "tslib": "^2.3.0",
    "zone.js": "^0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.4",
    "@angular/cli": "~11.0.4",
    "@angular/compiler-cli": "~11.0.4",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
  }
```


### Anything else?

_No response_