【问题标题】:How to communicate from mat dialog component to the component where mat dialog is implemented?如何从 mat 对话框组件与实现 mat 对话框的组件进行通信?
【发布时间】:2018-06-05 18:24:26
【问题描述】:

我有一个对话框组件和应用程序组件,其中实现了材质对话框。 这是应用组件的代码

import { Component } from '@angular/core';
import {VERSION, MatDialog, MatDialogRef} from '@angular/material';
import { DialogComponent } from '../dialog.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular 5';
  DialogRef: MatDialogRef<DialogComponent>;
  constructor(private dialog: MatDialog) {}
  ngOnInit() {
  }
  addItem() {
    this.DialogRef = this.dialog.open(DialogComponent);
  }

receiveMessageFromDialogComponent() {
  // how to receive message from dialog component
}
closeDialog(): void {
  this.DialogRef.close();
}
}

对话框组件是实现表单的地方,我需要在这里获取表单值并接收它。我尝试使用角度输入和输出来实现这一点,但是由于没有孩子和父母的交流,所以很有效。 这是对话框组件

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

@Component({
  template: `
    <h1 mat-dialog-title>Add Item</h1>
    <mat-dialog-content>
    <mat-form-field  class="example-full-width">
        <input matInput placeholder="Item name here...">
    </mat-form-field>
    </mat-dialog-content>
    <mat-dialog-actions>
      <button mat-button (click)="saveMessage()">Add</button>
      <button mat-button (click)="closeDialog()">Cancel</button>
    </mat-dialog-actions>
  `
})
export class DialogComponent {
  saveMessage() {
    console.log('how to send data to the app component');
  }
  closeDialog() {
    console.log('how to close');
  }
}

Working Example on StackBlitz

【问题讨论】:

标签: angular angular-material angular-cli mat-dialog


【解决方案1】:

您实际上可以使用订阅@OutputMatDialogRef&lt;DialogComponent&gt; 实现通信。对于某些情况,您可能需要在对话框关闭之前从对话框中获取数据。因此,我们不能使用this.DialogRef.afterClosed() 函数,因为我们必须先关闭对话框才能获取数据。相反,我们想要获取 Component 实例并从那里访问。

在您的 DialogComponent 上:

export class DialogComponent {
 
  @Output() submitClicked = new EventEmitter<any>();

  constructor(public dialogRef: MatDialogRef<DialogComponent>){}

  saveMessage() {
    this.submitClicked.emit('Your data');
  }

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

在您的 AppComponent 上:

openDialog() {
    this.dialogRef = this.dialog.open(DialogComponent);
    this.dialogRef.componentInstance.submitClicked.subscribe(result => {
        console.log('Got the data!', result);
    });
}

最好确保unsubscribe() 你所有的Subscriptions。像这样可以快速取消订阅(如果不涉及数据验证):

const dialogSubmitSubscription = this.dialogRef.componentInstance.submitClicked
    .subscribe(result => {
      console.log('Got the data!', result);
      // do something here with the data
      dialogSubmitSubscription.unsubscribe();
    });

此外,如果需要,您可以随时使用this.dialogRef.close() 关闭来自AppComponent 的对话框。或者在上面的例子中,你也可以使用this.DialogRef.componentInstance.closeDialog()

【讨论】:

【解决方案2】:

如果您想在对话框中编辑某些数据,然后将编辑后的数据从对话框传回组件,这是一个用例场景。我使用了上面的示例,但我合并了答案以使其更容易理解。假设数据来自服务,此示例将数据从 mat-dialog 组件共享到同一文件中的应用程序组件。

// app.component.html  

<div *ngFor="let a of appData">
  <p>{{a.name}}</p>
<button> (click)="open(event, a)">edit</button> 
</div>
// app.component.ts    

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
 appData: Array <any>;

 constructor(private dataService: DataService, public dialog: MatDialog) {}

 ngOnInit() {

   this.dataService.getData()
    .subscribe(res => { 
      //console.log(res);
      this.appData = res;
   })
 }

public open(event, data) {
  this.dialog.open(EditDialog, {
    data: data,
}).afterClosed()
  .subscribe(item => {
    // Edited Data sent to App Component from Dialog 
    console.log(item);
  });
 }
}

@Component({
  selector: 'edit-dialog',
  template: `<span>Edit Data</span>
             <mat-dialog-content>
               <input matInput name="title" type="text" class="form-control" placeholder="Edit Name" [(ngModel)]="dataItem.name">
             </mat-dialog-content>
             <div>
               <span><button mat-raised-button (click)="updateData()">Update Recipe</button></span>
             </div>`,
 })

 export class EditDialog implements OnInit {

   dataItem: any;  

   constructor(public dialogRef: MatDialogRef <EditDialog> , @Inject(MAT_DIALOG_DATA) public data: any, private dataService: DataService) {
     this.dataItem = this.data;
   }

   public updateData() {
     this.dialogRef.close(this.dataItem);
   }

   ngOnInit() {
   }
}

【讨论】:

    【解决方案3】:

    A.订阅this.DialogRefafterClosed Observable,可以在app.component.ts中调用this.DialogRef.open后添加这样的

      addItem() {
        this.DialogRef = this.dialog.open(DialogComponent);
        this.DialogRef.afterClosed()
        .subscribe(return => console.log(return));
      }
    

    B.在dialog.component.ts 中导入 MatDialog 服务,如下所示:

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

    C.确保 dialogRef 像这样传递给您的对话框构造函数

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

    C.在saveMessage()方法中,调用close dialog方法,将需要返回的值传递给app组件。

      saveMessage() {
        this.dialogRef.close('hello data');
      } 
    

    D. App 组件将收到该值,因为它订阅了 afterClosed 对话框 observable

    还可以查看完整的示例表单angular material docs

    干杯

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    相关资源
    最近更新 更多