31

I am using a MdDialogModule to show a Dialog window with an input field in it. The Modal is opening fine and I am able to enter text into input field and submit, but on clicking the Submit button, I want the data in the Input form to be returned to the Main Component that called the Dialog component and also close the Dialog.

How do I do this? I am able to pass data to MdDialog component, but didn't find any resource on how to return data to component from MdDialogComponent.

My Dialog component code looks like this

import { Component, OnInit, InjectionToken, Inject } from '@angular/core';
import { MD_DIALOG_DATA, MdDialogRef } from "@angular/material";

@Component({
  selector: 'app-add-book',
  templateUrl: './add-book.component.html',
  styleUrls: ['./add-book.component.css']
})
export class AddBookComponent {

  constructor() { }

}

and the method in main component calling the dialog box looks like this. No response is being returned now, it returns Undefined as I haven't figured it out yet.

openCreateDialog() {
    let dialogRef = this.dialog.open(AddBookComponent)
      .afterClosed()
      .subscribe(response => {
        console.log(response);
      });
  }
Nehal
  • 13,130
  • 4
  • 43
  • 59
Hisham Mubarak
  • 1,559
  • 3
  • 22
  • 28

4 Answers4

55

First, you need to add MdDialogRef to your dialog component

export class AddBookComponent {
  constructor(private dialogRef: MdDialogRef<AddBookComponent>) { }
}

Then use dialogRef.close to return the data

save() {
  this.dialogRef.close({ data: 'data' });
}
Harry Ninh
  • 16,288
  • 5
  • 60
  • 54
  • 1
    how do you get that from parent component? – Eray T May 24 '18 at 15:48
  • @ErayT isn't that something the asker has put in their question? – Harry Ninh May 24 '18 at 22:52
  • 1
    @HarryNinh That's right but I think they forgot. Anyways whoever looking for the solution: inside the parent component's constructor add "@Inject(MAT_DIALOG_DATA) public data: any" then you can get it by using "this.data.data" – Eray T May 25 '18 at 13:10
  • Oh, you got it the other way around. `@Inject(MAT_DIALOG_DATA)` should be put in the child (aka. the dialog), not the parent (aka the one who wants to pop the dialog up). – Harry Ninh May 26 '18 at 05:22
  • 1
    For new versions, make sure that you use `MatDialogRef` instead `MdDialogRef`. Also if you want to pass data to this AddBookComponent, you need to add to constructor `@Inject(MAT_DIALOG_DATA) data: any`. – hastrb Mar 26 '19 at 10:35
  • Lol, this doesn't actually answer the question. – Phil Apr 09 '20 at 17:22
  • closeDialog() { this.dialogRef.close({ event: 'close', data: this.fromDialog }); } – Alam Oct 21 '21 at 09:43
15

Thanks for Harry's comment first...

below is the whole related script

Component ts:

  let dialogRef = this.dialog.open(DataListDialogComponent, dialogConfig).afterClosed()
  .subscribe(response => {
    console.log(response);
  });

dialog ts:

    this.dialogRef.close({data:'data'});
W Kenny
  • 1,855
  • 22
  • 33
1

The "dialog.open" can be used to open the dialog component.

You can specify what data you would like to send to the dialog component by adding a second parameter. This can contain information like width and height check docs for more.

To close you can use ref.close().

If you want are expecting data from dialog then you can use ref.componentInstance.updatedSelectedArms which is an event fired when needed

var ref = this.dialog.open(SelectLoadingArmComponent, {
  width: '500px',
  data: { 
    loadingArms: this.loadingArms, 
    selectedloadingArms: this.selectedloadingArms
  }
});

ref.componentInstance.updatedSelectedArms.subscribe(
  (data) => {
    console.log(data)
    ref.close()
  }
);
Rohan Shenoy
  • 805
  • 10
  • 23
1

The other answers already answers the question. But let me provide a more verbose explanation of the solution I used in my use-case.

My requirement was to create a confirm Delete button in dialog. So I want to receive the result whether user confirmed to delete or not.

So my reusable Dialog component look like below:

import { Component, Inject } from "@angular/core";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
import { ConfirmDialogDAO } from "./confirm.dialog.dao";

@Component({
    templateUrl: "./confirm.dialog.html"
})
export class ConfirmDialog {

    constructor(@Inject(MAT_DIALOG_DATA) public data: ConfirmDialogDAO,
                private dialogRef: MatDialogRef<ConfirmDialog>) {
    }

    yesButtonClicked(): void {
        this.dialogRef.close(true);
    }

}

The above dialogRef is important because using that you can emit events based on user action on that component while dialog gets closed.

In my case, I only wanted to emit event when user clicked on confirm delete button. So the below is my html in dialog component:

<h1 mat-dialog-title>{{ data.title }}</h1>
<div mat-dialog-content>
  {{ data.description }}
</div>
<div mat-dialog-actions>
    <button mat-raised-button mat-dialog-close color="warn" (click)="yesButtonClicked()">{{ data.yesButtonName }}</button>
    <button mat-raised-button mat-dialog-close color="accent" cdkFocusInitial>{{ data.noButtonName }}</button>
</div>

If you notice, only when user clicks on +ve confirmation button, then I am emitting an event.

Now in the actual component where I wanted to reuse this dialog, this is how I invoked the dialog and performed action on data return:

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

@Component({
  templateUrl: './another.component.html',
  styleUrls: ['./another.component.css']
})
export class AnotherComponent {

constructor(private dialog: MatDialog) { }

deleteInputNode(): void {
    this.dialog.open(ConfirmDialog, {
      data: {
        title: `Delete input node?`,
        description: `Please confirm:`,
        yesButtonName: `Delete`,
        noButtonName: `Cancel`
      },
    }).afterClosed().subscribe(data => {
      if (data) {
        alert("Delete"); // Perform one action
      } else {
        alert("Not delete");  // Perform another action
      }
    });
  }

}

So subscribing to afterClosed() event will give us access to data returned from dialog component.

In my case, I only returned true / false value, but you can also emit objects: {key: value}. So in that case you can access that data in afterClosed() subscription using data.key.

Resource: Refer to this live example from stackblitz in case my explanation lacks some details: https://stackblitz.com/edit/matdialog-return-data-demo-qqscz9?file=app%2Ffile-name-dialog.component.ts

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Pran Kumar Sarkar
  • 953
  • 12
  • 26