Как получить экземпляр Component из ViewContainerRef.get() для компонентов, созданных динамически

Краткое изложение того, чего я пытаюсь достичь

  • динамически добавлять компоненты в ViewContainerRef (сделанный)
  • инициализировал эти динамические компоненты со свойствами (готово)
  • получить доступ к динамически создаваемым экземплярам Component, чтобы я мог принимать решения на основе того, что есть.

проблема

  • при динамическом добавлении компонентов они добавляются в ViewContainerRef
  • ViewContainerRef предлагает такие методы, как get(index) это возвращение ViewRef.
  • ViewRef не имеет никакого отношения к Component например, затрудняет получение необходимых данных

Вот ссылка на Stackblitz с рабочим кодом, показанным ниже (для динамического создания компонентов)

то appComponent начинается с создания нескольких компонентов с использованием ComponentFactoryResolver, и добавив их в ViewChildопределено в шаблоне. каждый DynamicComponent инициализируется id значение свойства, на которое мы пытаемся сослаться после создания

@Component({
  selector: "my-app",
  template: `
    <h3>Retrieving Component Reference for Dyamic Compnents</h3>
    <button (click)="getCompRef()">Get References</button>
    <div>
      <ng-container #childCont></ng-container>
    </div>
    <div>
      <small>List out the Ids from the dynamic components</small> <br />
      {{ createdItemIds | json }}
    </div>
  `,
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements AfterViewInit {
  @ViewChild("childCont", { read: ViewContainerRef })
  childCont: ViewContainerRef;

  createdItemIds: string[] = [];

  itemLimit = 5;

  constructor(
    private fr: ComponentFactoryResolver,
    private cdr: ChangeDetectorRef
  ) {}

  ngAfterViewInit(): void {
    for (let i = 0; i < this.itemLimit; i++) {
      const factory = this.fr.resolveComponentFactory(DynamicComponent);
      const compRef = this.childCont.createComponent(factory, i);
      // Set the id of the instance so that we can use it later
      compRef.instance.id = i + 1;
      this.cdr.detectChanges();
    }
  }
  ...
}

то DynamicComponentдобавление довольно просто. для упрощения он содержит только один id собственность, которую мы пытаемся получить

@Component({
  selector: "dynamic-component",
  template: `
    <div>Dynamic Component: {{ id }}</div>
  `,
  styles: [``]
  ]
})
export class DynamicComponent {
  id: number;
} 

Пока все хорошо.

  • Компоненты создаются динамически
  • экземпляры компонента инициализируются идентификатором, который мы можем видеть по жирности, отображаемой в пользовательском интерфейсе

проблема возникает при попытке получить свойство ID из компонентов DynamicallyCreated.

в AppComponent, когда пользователь нажимает кнопку, getCompRef() вызывается метод, который проходит по каждому дочернему элементу childCont (ViewContainerRef)

getCompRef(): void {
  for (let i = 0; i < this.itemLimit; i++) {
    const viewRef = this.childCont.get(i);
    // How do I get at the instance of the view  in order to obtain id?
    // the view Ref doesn't provide access to the instance
    // console.log(viewRef);
  }
}

Тем не менее ViewRef вернулся из ViewContainerRef.get() является подклассом ChangeDetectoreRef и не содержит ссылки на рассматриваемый экземпляр.

Изучая эту проблему, он попытался пойти по пути использования ViewChildren чтобы получить создаваемые компоненты списка, но это не сработало из-за таких проблем, как

  • https://github.com/angular/angular/issues/8785
  • или примеры предполагают, что директива, используемая в ViewChildren selector для компонента, который был предопределен в шаблоне
  • Я вижу много вопросов в отношении некоторых людей, которые хотят получить ViewRef, когда у них есть Component.instance, но в данной ситуации это бесполезно.

В конечном итоге мой вопрос:

  • есть ли простой способ получить экземпляр Component из ViewRef что я скучаю

Любая помощь приветствуется.

благодарю вас.

1 ответ

Я мог сделать это, только отслеживая экземпляры этих компонентов в другом массиве.

      @Component({
  selector: "my-app",
  template: `
    <h3>Retrieving Component Reference for Dyamic Compnents</h3>
    <button (click)="getCompRef()">Get References</button>
    <div>
      <ng-container #childCont></ng-container>
    </div>
    <div>
      <small>List out the Ids from the dynamic components</small> <br />
      {{ createdItemIds | json }}
    </div>
  `,
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements AfterViewInit {
  @ViewChild("childCont", { read: ViewContainerRef })
  childCont: ViewContainerRef;

  createdItemIds: string[] = [];

  itemLimit = 5;
  private dynamicComponentsArray: ComponentRef<DynamicComponent>[] = [];

  constructor(
    private fr: ComponentFactoryResolver,
    private cdr: ChangeDetectorRef
  ) {}

  ngAfterViewInit(): void {
    for (let i = 0; i < this.itemLimit; i++) {
      const factory = this.fr.resolveComponentFactory(DynamicComponent);
      const compRef = this.childCont.createComponent(factory, i);
      // Set the id of the instance so that we can use it later
      compRef.instance.id = i + 1;
      this.dynamicComponentsArray.push(compRef);
      this.cdr.detectChanges();
    }
  }
  
  getCompRef(): void {
      for (let i = 0; i < this.itemLimit; i++) {
        const viewRef = this.childCont.get(i);
        if (this.dynamicComponentsArray.length > 0) {
            for (let i = 0; i < this.dynamicComponentsArray.length; i++) {
                const componentRef = this.dynamicComponentsArray[i];
                const component = (componentRef) as ComponentRef<DynamicComponent>;
                let value = component.instance.id;
            }
        }
      }
    }
}
Другие вопросы по тегам