angular - Hur får jag åtkomst till komponentinstansen från koden?


Jag använder en ngComponentOutlet för att dynamiskt visa en komponent som tillhandahålls av anroparen. Min kod vet absolut ingenting om den tillhandahållna komponenttypen. Mallen kokar ner till detta:

<div [innerText]="options.title"></div>
<ng-container *ngComponentOutlet="options.componentType"></ng-container>
<button (click)="showInfo()">Info</button>

Om man talar på ett förenklat sätt, skickar anroparen för mitt användargränssnitt ett konfigurationsobjekt liknande följande:

export interface DisplayOptions<TComponent> {
  readonly componentType: Type<TComponent>;
  
  readonly title: string;
  
  readonly onClickInfo: (cmp: TComponent) => void;
}

Gränssnittet runt komponentuttaget innehåller ett par knappar, såsom en Info-knapp som visas ovan. När den Info-knappen klickas, bör onClickInfo-funktionen anropas, vilken behöver få en referens till komponenten.

Inuti den showInfo() funktionen, hur får jag tag på referensen till komponentinstansen i komponentutloppet?

Svar #1

Du bör kunna få en referens till denna komponent med hjälp av en @ViewChild.

  1. Se till att du har importerat NgComponentOutlet.
  2. Importera ViewChild
  3. Skapa en @ViewChild för att få en referens till komponentdirektivet:
  •  @ViewChild(NgComponentOutlet, { static: false }) ngComponentOutlet: NgComponentOutlet;
  1. Ändra din showinformation:
  • showInfo() { om (this.ngComponentOutlet) { const componentInstance=this.ngComponentOutlet['_componentRef'].instance; this.options.onClickInfo(componentInstance); } }

Ett fullständigt exempel skulle se ut ungefär så här:

import { Component, Type, ViewChild, NgComponentOutlet } from '@angular/core';

export interface DisplayOptions<TComponent> {
  readonly componentType: Type<TComponent>;
  readonly title: string;
  readonly onClickInfo: (cmp: TComponent) => void;
}

@Component({
  selector: 'app-dynamic',
  template: `
    <div [innerText]="options.title"></div>
    <ng-container *ngComponentOutlet="options.componentType"></ng-componentOutlet>
    <button (click)="showInfo()">Info</button>
  `
})
export class DynamicComponent<TComponent> {
  @ViewChild(NgComponentOutlet, { static: false }) ngComponentOutlet: NgComponentOutlet;
  options: DisplayOptions<TComponent>;

  showInfo() {
    if (this.ngComponentOutlet) {
      const componentInstance = this.ngComponentOutlet['_componentRef'].instance;
      this.options.onClickInfo(componentInstance);
    }
  }
}

Du frågar ComponentOutlet med hjälp av @ViewChild och lagrar det i ngComponentOutlet-egenskapen. showInfo() kan då få åtkomst till ['_componentRef'].instance-egenskapen hos ngComponentOutlet.

Ett annat sätt att göra detta skulle vara att använda en @Input som är liknande, men du skulle behöva uppdatera HTML och skicka in en primärnyckel som du kan använda som ett Id.