材质对话框afterOpened与AfterViewInit。在AfterViewInit中访问对话框数据是否安全?

时间:2019-09-18 13:27:30

标签: angular angular-material

我以标准方式打开对话框:

this.dialogRef = this.dialog.open(DialogComponent, {
      width: '90vw',
      height: '85vh',
      ....

然后在DialogComponent中,我在ngAfterViewInit中访问对话框数据:

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

  ngAfterViewInit() {
    this.data = this.data.width

(这是一个伪代码)。如您所见,我不使用:

this.dialogRef.afterOpen().pipe( ...

谁能解释this.dialogRef.afterOpenngAfterViewInit之间的区别?

AfterViewInit 中访问data是否安全?

3 个答案:

答案 0 :(得分:2)

ngAfterViewInit是一个Angular钩子,用于在该组件实例see here for more information的生命周期中的某个时刻之后执行功能。

MatDialogRef.afterOpened是打开MatDialog的给定实例时可观察到的通知。

基本上,应在对话框的视图初始化后从对话框内部使用ngAfterViewInit来执行操作,打开对话框的组件应使用MatDialogRef.afterOpened来在打开对话框时执行操作但尚未关闭。

由于数据已注入构造函数中,因此在视图初始化期间它们已经存在,因此在该阶段可以安全使用它们。

答案 1 :(得分:1)

阅读DialogComponent See Details的源代码之后

this.dialogRef.afterOpen将在组件的动画完成时触发。

其中ngAfterViewInit

import { Component } from '@angular/core';

@Component({
   selector: 'app-lifecycle-hook',
   template: `
     <h3>Lifecycle Hook Demo</h3>
    `
})
export class LifecycleHookComponent { 
  constructor() {
    console.log("---constructor---");
  }
  ngOnInit() {
    console.log("---Inside ngOnInit---");
  }
  ngDoCheck() {
    console.log("---Inside ngDoCheck---");
  }
  ngAfterContentInit() {
    console.log("---Inside ngAfterContentInit---");
  }
  ngAfterContentChecked() {
    console.log("---Inside ngAfterContentChecked---");
  }
  ngAfterViewInit() {
    console.log("---Inside ngAfterViewInit---");
  }  
  ngAfterViewChecked() {
    console.log("---Inside ngAfterViewChecked---");    
  }
  ngOnDestroy() {
    console.log("---Inside ngOnDestroy---");      
  }
}

输出:

---constructor--- 
---Inside ngOnInit--- 
---Inside ngDoCheck---
---Inside ngAfterContentInit---
---Inside ngAfterContentChecked---
---Inside ngAfterViewInit---
---Inside ngAfterViewChecked--- 

因此您可以在NgOnInit上使用,也可以在ngAfterViewInit获取数据之后使用

答案 2 :(得分:0)

不是直接的答案,但它可以帮助使用 afterOpened。在你的组件类中注入一个对话框实例,然后使用 templateRef 打开模式,就像使用在模块的 entryComponents 数组中声明的组件一样。下面提供了 StackBlitz 中的演示。

@ViewChild('widgetEditorModal') public widgetEditorModal: TemplateRef<any>;
private widgetEditorDialogRef: MatDialogRef<TemplateRef<any>>;

isModalOpen = false;

constructor(public dialog: MatDialog) {}

openWidgetEditorDialog() {

  const dialogConfig = new MatDialogConfig();
  dialogConfig.role = 'dialog';
  dialogConfig.width = '720px';

  // widgetEditorModal is my modal templateRef
  this.widgetEditorDialogRef = this.dialog.open(this.widgetEditorModal, dialogConfig);

  this.widgetEditorDialogRef.afterOpened().subscribe(result => {
      this.isModalOpen = true;
      console.log('widgetEditorModal has been opened!');
  });

  this.widgetEditorDialogRef.afterClosed().subscribe(result => {
      this.isModalOpen = false;
      console.log('widgetEditorModal has been close!');
  });
}

还有模板部分:

<button mat-raised-button color="primary" (click)="openWidgetEditorDialog()">Open modal</button>

<ng-template #widgetEditorModal>
  <div class="mat-dialog-header border-bottom">
    <h3 class="mat-h3 mb-0">Widget settings</h3>
    <div fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="12px">
      <button mat-icon-button matDialogClose tabindex="-1">
        <mat-icon aria-label="Close dialog">close</mat-icon>
      </button>
    </div>
  </div>
  <mat-dialog-content>
    <div class="py-5">Your settings form here</div>
  </mat-dialog-content>
  <mat-dialog-actions class="border-top">
    <button type="button" mat-button matDialogClose>Cancel</button>
    <button type="button" mat-raised-button color="accent">Save changes</button>
  </mat-dialog-actions>
</ng-template>

StackBlitz demo here