How to communicate from mat dialog component to the component where mat dialog is implemented?
You can actually achieve communication using subscription to @Output
through MatDialogRef<EditDialog>
. For some scenarios, you may need to get the data from a dialog before it is closed. Hence, we cannot make use of the this.DialogRef.afterClosed()
function since we have to close the dialog first to get the data.
On your DialogComponent:
export class DialogComponent {
@Output() submitClicked = new EventEmitter<any>();
constructor(public dialogRef: MatDialogRef<DialogComponent>){}
saveMessage() {
const data = 'Your data';
this.submitClicked.emit(data);
}
closeDialog() {
this.dialogRef.close();
}
}
On your AppComponent:
addItem() {
this.DialogRef = this.dialog.open(DialogComponent);
this.DialogRef.componentInstance.submitClicked.subscribe(result => {
console.log('Got the data!', result);
});
}
Better make sure to unsubscribe()
all your Subscription
s. Something like this will do for a quick unsubscribe (if there's no validation of data involved):
const dialogSubmitSubscription = this.DialogRef.componentInstance.submitClicked
.subscribe(result => {
console.log('Got the data!', result);
dialogSubmitSubscription.unsubscribe();
});
Also, you can always close your dialog from the AppComponent
with this.DialogRef.close()
if you have to.
A use case scenario if you want to edit some data in a dialog then pass the edited data back to the component from the dialog. I used the example above but I consolidated the answer to make it easier to follow. Assuming the data is coming from a service this example shares data from a mat-dialog component to an app component in the same file.
// 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() {
}
}
A. subscribe to the afterClosed
Observable of this.DialogRef
, you can add it after you call the this.DialogRef.open
in app.component.ts Like this
addItem() {
this.DialogRef = this.dialog.open(DialogComponent);
this.DialogRef.afterClosed()
.subscribe(return => console.log(return));
}
B. In dialog.component.ts
import the MatDialog service, like this:
import { Component, Inject } from '@angular/core';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from'@angular/material';
C. Make sure that the dialogRef is passed to your dialog constructor like this
constructor(public dialogRef: MatDialogRef<DialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) {}
C. In the saveMessage()
method, call the close dialog method and pass the value that you need to return to app component.
saveMessage() {
this.dialogRef.close('hello data');
}
D. App component will receive the value because it subscribe to the afterClosed
dialog observable
Also take a look at the full example form angular material docs
Cheers