如何向Angular Material 2的对话框传递数据

120

我正在使用 Angular Material2 的 对话框

我想向已打开的组件传递数据。下面是我在单击按钮时打开对话框的方式:

let dialogRef = this.dialog.open(DialogComponent, {
            disableClose: true,
            data :{'name':'Sunil'}
        });

在文档页面上有数据属性,但我已经检查了我安装的软件包中的MdDialogConfig。

/**
 * Configuration for opening a modal dialog with the MdDialog service.
 */
export declare class MdDialogConfig {
    viewContainerRef?: ViewContainerRef;
    /** The ARIA role of the dialog element. */
    role?: DialogRole;
    /** Whether the user can use escape or clicking outside to close a modal. */
    disableClose?: boolean;
    /** Width of the dialog. */
    width?: string;
    /** Height of the dialog. */
    height?: string;
    /** Position overrides. */
    position?: DialogPosition;
}

配置类中没有数据属性。

那么我该如何访问传递的数据?

7个回答

391
对话框的最新版本(这是 Angular 5 之前的版本,有关 Angular 5,请参见下面的更新),您可以通过配置传递数据,这样做会更简单和清晰。
打开对话框时,您可以通过将数据作为配置参数添加来进行操作(只需忽略用于说明目的的宽度和高度):
this.dialogRef = this.dialog.open(someComponent, {
  width: '330px',
  height: '400px',
  data: {
    dataKey: yourData
  }
});

然后在对话框中打开的组件中,您可以像这样访问它:

import {MAT_DIALOG_DATA} from '@angular/material';
import { Inject } from '@angular/core';


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

ngOnInit() {
  // will log the entire data object
  console.log(this.data)
}

或者你可以在模板或其他方法中使用它,但你明白了。

Angular 5更新

在Angular 5中,所有的材料都从Md更改为Mat,所以如果要导入,请使用以下方式:

import {MAT_DIALOG_DATA} from '@angular/material'

然后像这样注入

@Inject(MAT_DIALOG_DATA) public data: any

针对Angular 9的更新

MAT_DIALOG_DATA的导入位置已更改为:

import {MAT_DIALOG_DATA} from '@angular/material/dialog';

100
任何回来编辑他们的帖子并为新框架版本提供更新代码的人都会得到点赞,谢谢! - Aaron Jordan
1
这是我第二次需要参考这个答案,上次忘记点赞了。 - Robbie Smith
2
更新后的解决方案完美地运行了。谢谢。 - Soulzityr
1
完全正确的更新!感谢您提供的解决方案! - manjiro sano

46

我想为那些还在学习的人提供更详细的答案:

与我配置 Material 示例不同,我将对话框配置为具有自己的组件文件(html、css 和 ts)以便于调试。

主组件文件 "x.component.ts" (调用对话框)

1)添加导入语句

import { MatDialog} from '@angular/material';

2) 将该属性添加到构造函数参数中。

public dialog: MatDialog

3) 定义调用对话框的代码

  openDialog(title: string, text: string): void {
const dialogRef = this.dialog.open(DialogComponent, {
  width: '350px',
  data: {dialogTitle: title, dialogText: text}
);

dialogRef.afterClosed().subscribe(result => {
});

  const dialogSubmitSubscription = 
  dialogRef.componentInstance.submitClicked.subscribe(result => {
  dialogSubmitSubscription.unsubscribe();
});

在您的HTML文件中使用openDialog()函数调用该函数。我正在引用DialogComponent,请确保它已经导入到您的模块中。

import { DialogComponent } from './dialog/dialog.component';

同样也

entryComponents: [DialogComponent]

在entryComponents数组中声明它

4)在dialog.component.ts文件中添加导入

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

5) 定义属性和函数

dialogTitle: string;
dialogText: string;
@Output() submitClicked = new EventEmitter<any>();

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


  ngOnInit() {
    this.dialogTitle = this.data.dialogTitle;
    this.dialogText = this.data.dialogText;
  }

  saveMessage() {
    const data = 'Your data';
    this.submitClicked.emit(data);
    this.dialogRef.close();
  }

  closeDialog() {
    this.dialogRef.close();
  }

最后是HTML

<h1 mat-dialog-title>{{dialogTitle}}"</h1>
<div mat-dialog-content>
  <p>{{dialogText}}</p>

</div>
<div mat-dialog-actions>
  <button mat-button (click)="saveMessage()" >Ok</button>
  <button mat-button (click)="closeDialog()" cdkFocusInitial>No Thanks</button>

</div>

希望它有所帮助。


1
这非常有帮助,谢谢。虽然文档中有这些信息,但对我来说并不是很清晰,这让我能够快速上手。谢谢! - Todd Davis
非常完整的答案!谢谢! - Nilson Aguiar
正是我所需要的! - GIVE-ME-CHICKEN
1
@Darren,你好,谢谢你提供这个例子。我遇到了“无法找到名称'DialogData'”的问题。有什么想法吗? - touinta
1
对话框数据是您从主组件传递到对话框组件的对象。@Inject(MAT_DIALOG_DATA)public data:DialogData。您在对话框构造函数中注入它。实际类型是根据您的需求自己定义的。我的示例称为DialogData,但可以是任何内容或仅是对象文字。 - Darren Street

42

更新 2(Angular 5+)

这个答案已经比较过时了。请看epiphanatic的答案

更新

您可以使用dialogRef.componentInstance.myProperty = '一些数据'来设置组件上的数据。

您需要像这样:

let dialogRef = this.dialog.open(DialogComponent, {
            disableClose: true,
        });
dialogRef.componentInstance.name = 'Sunil';

然后在您的 DialogComponent 中,您需要添加您的 name property

...

@Component({
  ...
})
export class DialogComponent {
   public name: string;

   ...

}

以下文本在更新版本的@angular/material中无效

我没有找到任何相关文档,所以我也开始查看源代码。因此,这可能不是官方的操作方式。

我成功地在dialogRef._containerInstance.dialogConfig.data中找到了数据;

所以你可以做的事情是,例如

let name = dialogRef._containerInstance.dialogConfig.data.name;
console.log(name); // Sunil

dialogRef._containerInstance 未定义。我已经检查了 MdDialogRef,没有 _containerInstance 属性。 - Sunil Garg
@SunilGarg,你是对的,我尝试使用旧版本的库。在更新版本中,MdDialogConfig接口实际上已经删除了数据属性。 - Fredrik Lundin
我尝试更新材料库,但遇到了这个问题:http://stackoverflow.com/questions/42667276/how-to-update-angular-material2-using-npm-properly - Sunil Garg
我尝试了同样的方法,并在DialogComponent的构造函数中尝试console.log(this.name);,但没有起作用。 - Sunil Garg
在这种情况下,你不会将它传递给构造函数,而是在组件创建后设置它。所以你需要在稍后的生命周期钩子中检查它,或者只需在你的模板中绑定它 @SunilGarg - Fredrik Lundin
让我们在聊天中继续这个讨论 - Sunil Garg

5

对于Angular 13,要将一个对象传递到对话框数据结构中,我必须使用以下代码:

const dialogRef = this.dialog.open(MyDialog, {
  data: { myObjectHolder: myObject }
});

然后在对话框类中使用以下内容:

private myObject: MyObjectClass;

constructor(@Inject(MAT_DIALOG_DATA) data: { myObjectHolder: MyObjectClass }) {
    this.myObject = data.myObjectHolder;
}

4

对于寻找 Angular 10 或 11 的人来说,唯一的区别在于您使用:

import {MAT_DIALOG_DATA} from '@angular/material/dialog';

改为:

import {MAT_DIALOG_DATA } from '@angular/material';

官方页面在这里


1
所以我已经添加了这个方法,并且它在一个组件上运行,但如果我想制作一个对话框(另一个组件),它就不起作用了。
表格和删除按钮的组件。
  openDeleteDialog(user) {
    this.dialog.open(DeleteUserDialogComponent, {
      width: '30%', disableClose: true, data: user
    });
  }

组件对话框
export class DeleteUserDialogComponent {

  dataSource = new MatTableDataSource();

  constructor(public dialog: MatDialog, public dialogRef: MatDialogRef<DeleteUserDialogComponent>, private userService: UserService, @Inject(MAT_DIALOG_DATA) public data: any) {}


  deleteUser() {
    this.dataSource.data.splice(this.dataSource.data.indexOf(this.data), 1);
    this.dataSource.data = [...this.dataSource.data];
    console.log(this.dataSource.data);
    console.log(this.data)
  }

  click(): void {
    this.dialogRef.close();
  }
}

0

如果您正在使用对话框处理HTTP数据,请记住RxJS和Observables非常适合解决此问题。

对话框服务:

    private _dialogDataSubj$ = new Subject<DialogData>();
    dialogData$ = this._dialogDataSubj$.asObservable()

    setDialogData(data: DialogData) {
        this._dialogDataSubj$.next(data)
    }

在 HTML 对话框中:

<ng-container *ngIf="dialogData$ | async as data; else doneTmp">

我不确定是不是只有我这样,但我无法仅使用对话框数据引用(@Inject)更新我的材料对话框中的数据,例如:dialogRef.data = newData


同样,我也遇到了这种问题,结果发现在更新时传递了错误类型的数据。如果您不想使用可观察对象,可以通过以下两种方式进行更新:
  1. 使用注入的数据对象并分配一个新对象。
  2. this.dialogRef.componentInstance.data = newData。
- Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接