Добавление и удаление динамического компонента Angular

У меня есть этот код в Angular 12, и он отлично работает. Проблема возникает при смене версии с 12 на 16.

import {
  ComponentRef,
  ComponentFactoryResolver,
  ViewContainerRef,
  ViewChild,
  Component,
ViewRef
} from "@angular/core";
import { ChildComponent } from "../child/child.component";

@Component({
  selector: "app-parent",
  templateUrl: "./parent.component.html",
  styleUrls: ["./parent.component.css"]
})
export class ParentComponent {
  @ViewChild("viewContainerRef", { read: ViewContainerRef })
  VCR: ViewContainerRef;

  child_unique_key: number = 0;
  componentsReferences = Array<ComponentRef<ChildComponent>>()

  constructor(private CFR: ComponentFactoryResolver) {}

  createComponent() {
    let componentFactory = this.CFR.resolveComponentFactory(ChildComponent);

    let childComponentRef = this.VCR.createComponent(componentFactory);

    let childComponent = childComponentRef.instance;
    childComponent.unique_key = ++this.child_unique_key;
    childComponent.parentRef = this;

    // add reference for newly created component
    this.componentsReferences.push(childComponentRef);
  }

  remove(key: number) {
    if (this.VCR.length < 1) return;

    let componentRef = this.componentsReferences.filter(
      x => x.instance.unique_key == key
    )[0];

    let vcrIndex: number = this.VCR.indexOf(componentRef as any);

    // removing component from container
    this.VCR.remove(vcrIndex);

    // removing component from the list
    this.componentsReferences = this.componentsReferences.filter(
      x => x.instance.unique_key !== key
    );
  }
}

Пример: https://stackblitz.com/edit/add-or-remove-dynamic-comComponent?file=src%2Fapp%2Fparent%2Fparent.comComponent.ts

Проблема в Angular 16 заключается в том, что vcrIndex всегда имеет значение -1, если не найден.

let vcrIndex: number = this.VCR.indexOf(componentRef as any);

// removing component from container
this.VCR.remove(vcrIndex);

Есть какие-нибудь предложения или как это исправить, не изменяя способ создания динамических компонентов? Я пробовал несколько вещей, например добавление индекса или идентификатора, но так и не смог решить проблему.

Спасибо

Я посмотрел, отличается ли структура видеомагнитофона, и мог бы добавить идентификатор и выполнить поиск вручную, но не смог.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не знаю, почему именно это сработало раньше, думаю, это было просто совпадение. this.VCR.indexOf на самом деле ожидает ViewRef, и вы передаете ComponentRef туда, приводя его к any.

Исправить это довольно просто, вам просто нужно передать componentRef.hostView на VCR.indexOf:

let vcrIndex: number = this.VCR.indexOf(componentRef.hostView);

Вот рабочая демо с использованием Angular 17.


На всякий случай, ComponentFactoryResolver уже давно устарел (v13), и вы можете передать тип компонента непосредственно в this.VCR.createComponent:

let childComponentRef = this.VCR.createComponent(ChildComponent);

Другие вопросы по теме