Динамически загружать компонент внутри MatDialog материала

может ли кто - нибудь привести пример того, как динамически загружать компонент в материальный Матдиалог?

то, что я хотел бы сделать, это следующее: Я предоставлю Данные конфигурации MatDialog с типом компонента, который диалог затем создаст экземпляр и разместит внутри его области mat-dialog-content.

похоже, мне нужно будет использовать некоторую комбинацию ng-template и viewContainerRef, но я не знаю, как создать экземпляр предоставленного типа компонента и вставить в нужную область.

простой пример:

    <h2 mat-dialog-title>MyTitle</h2>
    <mat-dialog-content>
     <---- dynamically loaded component would be inserted here ---->
    </mat-dialog-content>

    <mat-dialog-actions>
      <button mat-button mat-dialog-close>Cancel</button>
      <button mat-button [mat-dialog-close]="true">Save</button>
    </mat-dialog-actions>

2 ответов


существуют различные варианты, такие как:

1) встроенная структурная директива ngComponentOutlet

<ng-container *ngComponentOutlet="data.component"></ng-container> 

пример

2) используя угловой материал cdk. Точнее вы можете использовать PortalModule от вторичной точки входа @angular/cdk/portal

диалог.деталь.ТС

import { ComponentPortal } from '@angular/cdk/portal';

@Component({...})
export class DialogDialog {

  portal: ComponentPortal<any>;

  constructor(...
    @Inject(MAT_DIALOG_DATA) public data: any) { }

  ngOnInit() {
    this.portal = new ComponentPortal(this.data.component);
  }

диалог.деталь.HTML-код

<ng-template [cdkPortalOutlet]="portal"></ng-template>

пример

3) Использование angular API

диалог.деталь.ТС

@Component({...})
export class DialogDialog {

  @ViewChild('target', { read: ViewContainerRef }) vcRef: ViewContainerRef;

  componentRef: ComponentRef<any>;

  constructor(
    ...
    private resolver: ComponentFactoryResolver,
    @Inject(MAT_DIALOG_DATA) public data: any) { }

  ngOnInit() {
    const factory = this.resolver.resolveComponentFactory(this.data.component);
    this.componentRef = this.vcRef.createComponent(factory);
  }


  ngOnDestroy() {
    if (this.componentRef) {
      this.componentRef.destroy();
    }
  }  
}

диалог.деталь.HTML-код

<ng-template #target></ng-template

пример


фактический модальный компонент .ts: (обратите внимание, что модальный компонент html где вы напишете свой код выше)

import {Component, Inject, OnInit} from '@angular/core';
import {MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material';


@Component({
    selector: 'app-modal',
    templateUrl: './modal.component.html',
    styleUrls: ['./modal.component.css']
})
export class ModalComponent implements OnInit {

    constructor(public dialogRef: MatDialogRef<CreateFirmComponent>,
                @Inject(MAT_DIALOG_DATA) public data: any)
                 {
    }

    ngOnInit() {
    }

    onConfirm() {
        this.dialogRef.close(true);
    }

    onCancel(): void {
        this.dialogRef.close(false);
    }

}

и компонент, из которого вы вызываете модальное:

import {Component, OnInit} from '@angular/core';
import {MatDialog} from '@angular/material';
import {ModalComponent} from './modal-component';


@Component({
    selector: 'app-list',
    templateUrl: './list.component.html',
    styleUrls: ['./list.component.css']
})
export class ListComponent implements OnInit {


    constructor(public dialog: MatDialog) {
    }




    openDialog(): void {
        let dialogRef = this.dialog.open(ModalComponent, {
            width: '500px'
        });

        dialogRef.afterClosed().subscribe(result => {
            // result is what you get after you close the Modal
        });
    }

}