Picture of Brian Love wearing black against a dark wall in Portland, OR.

Brian Love

Passing Data with MdDialog

Make your Material MdDialog stateless by passing data as part of the MdDialogConfig object.

[Update April 11, 2017]

With the release of @angular/material version 2.0.0-beta.3 the config property of MdDialogRef has been removed. We now use the MD_DIALOG_DATA token to inject the data into our dialog’s component. See this GitHub issue.

Stateless

What do I mean by stateless? Let’s look at the definition of stateless from Wikipedia:

Of a system or protocol, such that it does not keep a persistent state between transactions.

In a basic sense, a component in our Angular application is considered stateful when it:

And, a component might be considered stateless when it:

Stateless components are sometimes referred to as dumb components.

Want to read more about stateless vs. stateful components? Check out Todd Motto’s article on Stateful and Stateless components.

Passing data in MdDialogConfig

First, let’s take a look at the MdDialogConfig interface:

/**
 * 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;
    /** Data being injected into the child component. */
    data?: any;
}

Note the data property. It allows us to inject data into the child component that is created when we open() an MdDialog. Here is an example component that opens the dialog and passes a User model object to the child component:

import { Component, Input } from "@angular/core";
import { MdDialog } from "@angular/material";

//dialog
import { InviteDialogComponent } from "../dialogs/invite-dialog/invite-dialog.component";

//model
import { User } from "../models/user";

/**
 * The invite card.
 * @class InviteCardComponent
 */
@Component({
  selector: "j11-invite-card",
  templateUrl: "./invite-card.component.html",
  styleUrls: ["./invite-card.component.scss"]
})
export class InviteCardComponent {

  //the authenticated user
  @Input() public user: User;

  /**
   * @constructor
   * @param {MdDialog} mdDialog
   */
  constructor(private mdDialog: MdDialog) { }

  /**
   * Open the dialog to send an invite
   * @method openInviteDialog
   */
  public openInviteDialog() {
    this.mdDialog.open(InviteDialogComponent, {
      disableClose: true,
      data: {
        user: this.user
      }
    });
  }
}

Let’s review the InviteCardComponent:

Accessing custom Data

First, we need to import the MD_DIALOG_DATA constant, which is really just an instance of the OpaqueToken class:

import { MdDialogRef, MD_DIALOG_DATA } from '@angular/material';

Next, use the @Inject() decorator to inject the data via our constructor() function:

constructor(@Inject(MD_DIALOG_DATA) private data: { user: User })

Now we just pick that data up inside our child component’s ngOnInit() method. Here is the full example:

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

//model
import { User } from "../models/user";

@Component({
  selector: "j11-invite-dialog",
  templateUrl: "./invite-dialog.component.html",
  styleUrls: ["./invite-dialog.component.scss"]
})
export class InviteDialogComponent implements OnInit {

  //authenticated user
  public user: User;

  /**
   * @constructor
   * @param {Object} data
   * @param {MdDialogRef<InviteDialogComponent>} mdDialogRef
   */
  constructor(
    @Inject(MD_DIALOG_DATA) private data: { user: User },
    private mdDialogRef: MdDialogRef<InviteDialogComponent>
  ) { }

  /**
   * Let's do this.
   * @method ngOnInit
   */
  public ngOnInit() {
    //set custom data from parent component
    this.user = this.data.user;
  }
}

OK, let’s review the code above:

That’s it. Super easy. Thanks to the @angular/material2 team!