Returning Data from MdDialog in Angular Material 2
Asked Answered
A

4

34

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);
      });
  }
Ari answered 12/8, 2017 at 8:6 Comment(0)
M
59

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' });
}
Mallard answered 12/8, 2017 at 8:13 Comment(7)
how do you get that from parent component?Lamplighter
@ErayT isn't that something the asker has put in their question?Mallard
@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"Lamplighter
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).Mallard
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.Cockahoop
Lol, this doesn't actually answer the question.Airiness
closeDialog() { this.dialogRef.close({ event: 'close', data: this.fromDialog }); }Uranic
M
19

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'});
Mortification answered 28/12, 2018 at 8:39 Comment(2)
This should be the accepted answer. The accepted one does not show how to handle the returned data.Stollings
@SilvioLangereis, the OP has taken care of that in the question.Muscular
H
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()
  }
);
Hi answered 18/1, 2019 at 10:52 Comment(0)
T
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

Thread answered 10/7, 2022 at 6:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.