Material Design Components For Angular

Part 2: Popups & Modals

Subscribe On YouTube

DemoCode

This is the second part of the Angular Material series on CodingTheSmartWay.com. In this part we’ll be focusing on Popups and Modals. Furthermore this second part assumes that you’re familiar with the Angular Material library in general and that you know how to setup an Angular project and install the Angular Material library in that project. If you’re new to Angular Material please first take a look at the first part of this series: Angular Material – Part 1 Introduction.

Dialog

The Angular Material library offers support for displaying modal dialogs in Material Design. To enable Angular Material Dialogs in your Angular application you need to import MdDialogModule in your main application module. Add the following import statement in file app.module.ts:

import {MdDialogModule} from '@angular/material';

Next, make sure to also add MdDialogModule to the imports array of @NgModule.

Now we’re ready to make use of the MdDialog service which is part of MdDialogModule in our components. Let’s create a new component for that purpose:

$ ng g component DialogDemo

This command creates the following four new files in our project:

src/app/dialog-demo/dialog-demo.component.css

src/app/dialog-demo/dialog-demo.component.html

src/app/dialog-demo/dialog-demo.component.spec.ts

src/app/dialog-demo/dialog-demo.component.ts

The component is automatically imported in app.module.ts, so that it can be used in our application. Add the following markup code in dialog-demo.component.html:

<md-card class="card1"> <md-card-header> <md-card-title><h1>Dialog Demo</h1></md-card-title> </md-card-header> <hr> <md-card-content> <button md-raised-button (click)="openDialog()">Open Dialog</button> <hr> <strong>Result: {{dialogResult}}</strong> </md-card-content> </md-card>

Here you can see that we’re making use of MdDialog, MdButton and MdCard elements and directives. To make those elements available in our application we need to adapt app.module.ts furthermore. First add the corresponding input statements:

import {MdCardModule} from '@angular/material'; import {MdButtonModule} from '@angular/material'; import {MdDialogModule} from '@angular/material';

And add the types to the imports array as well:

imports: [ BrowserModule, BrowserAnimationsModule, MdCardModule, MdButtonModule, MdDialogModule ],

To include the output of DialogDemoComponent in our output we need to add the component selector to the markup code of our main application component in file app.component.html:

<div style="text-align:center"> <app-dialog-demo></app-dialog-demo> </div>

The output look like the following in the browser:

Opening A Modal Dialog

We’ve already included a button in the template code for component DialogDemoComponent. The click event of this button has been connected with the openDialog() event handler method. If the user clicks on that button the modal dialog should be opened and displayed. Therefore the openDialog() method needs to be implemented in dialog-demo.component.ts. Before doing so, make sure that the MdDialog service is injected in the component class. Add the import statement on top of the file:

import {MdDialog} from '@angular/material';

and inject MdDialog service in the class constructor:

constructor(public dialog: MdDialog) {}

The method openDialog() is implemented in the following way:

openDialog() { let dialogRef = this.dialog.open(MyDialogComponent, { width: '600px', data: 'This text is passed into the dialog!' }); dialogRef.afterClosed().subscribe(result => { console.log(`Dialog closed: ${result}`); this.dialogResult = result; }); }

The MdDialog service object dialog is used to call the open method. The methods gets two parameter. The first parameter MyDialogComponent is the component which should be used for displaying the dialog content. MyDialogComponent is not existing yet, so we need to create this component in the next step.

The second parameter which is used is an object containing the properties width and data. By assigning the string 600px to property width we’re defining that the dialog should be of that width. If you like you can use the property hight here in the same way. The data property is a custom property which is containing a text string. This information can be accessed from inside the dialog.

The call of the open method is returning a reference to the dialog object which is of type MdDialogRef. Using this reference we’re able to programmatically close this dialog by calling the close method or subscribe to the afterClosed event. In our example from above we’re using the dialogRef.afterClosed().subscribe() method to subscribe to this event and register an event handler method. This method sets the dialogResult class property to the result value which is returned from the dialog. Later we’ll see how to set this value when closing the dialog.

Implementing The Dialog Component

Next we need to implement MyDialogComponent in our project. To generate the component we’re making use of Angular CLI once again. Execute the following command in the project directory:

$ ng g component MyDialog

Having generated the component we’re going to insert the template code first in file my-dialog.component.html:

<div> <h2 md-dialog-title>MY DIALOG</h2> <hr> <md-dialog-content> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aperiam maxime cum dolorem officiis assumenda rem alias, omnis nobis nam. Ratione soluta libero architecto cupiditate at fugit consectetur sit dignissimos vitae. <br> <br> <strong>{{data}}</strong> </md-dialog-content> <hr> <md-dialog-actions> <button md-raised-button (click)="onCloseConfirm()">CONFIRM</button> <button md-raised-button (click)="onCloseCancel()">CANCEL</button> </md-dialog-actions> </div>

As you can see we’re using MdDialog elements and directive to structure the content of the dialog. In the <md-dialog-actions> section two buttons are included.

The user can choose to close to dialog by using the button Confirm or Cancel. The click event of the Confirm button is connected to the onCloseConfirm() event handler method and the click event of the Cancel button is connected to the onCloseCancel() event handler method. In the next section we’ll see what’s the exact difference.

Closing A Dialog

In the following code listing you can see the implementation of both event handler methods in my-dialog.component.ts:

import { Component, OnInit, Inject } from '@angular/core'; import {MD_DIALOG_DATA} from '@angular/material'; import {MdDialogRef} from '@angular/material'; @Component({ selector: 'app-my-dialog', templateUrl: './my-dialog.component.html', styleUrls: ['./my-dialog.component.css'] }) export class MyDialogComponent implements OnInit { constructor(public thisDialogRef: MdDialogRef<MyDialogComponent>, @Inject(MD_DIALOG_DATA) public data: string) { } ngOnInit() { } onCloseConfirm() { this.thisDialogRef.close('Confirm'); } onCloseCancel() { this.thisDialogRef.close('Cancel'); } }

The MdDialogRef service is injected into the component, so that we can call the method close() of this service to close the dialog. The close() methods takes one string parameter. This parameter is used to inform the calling component of the result of this dialog. If the user clicks on button Confirm the string ‘Confirm’ is returned and of the user clicks on button Cancel the string ‘Close’ is returned.

As seen before the return value of the dialog is processed in the DialogDemoComponent:

dialogRef.afterClosed().subscribe(result => { console.log(`Dialog closed: ${result}`); this.dialogResult = result; });

The string which is returned is available via the result parameter of the function which is registered for the subscription of the Observable which is returned by the afterClosed() method of the dialog. Within that function the result value (‘Confirm’ or ‘Closed’) is assigned to the class property dialogResult. An expression to output the value of dialogResult is embedded in the component’s template code, so that the user is able to see the result:

SHARING Data With A Dialog

When opening the dialog by calling the open() method in DialogDemoComponent we passed in a second parameter. This object contains the data property:

let dialogRef = this.dialog.open(MyDialogComponent, { width: '600px', data: 'This text is passed into the dialog!' });

Let’s take a look at the code which is needed inside the dialog to access the data value and display this value to the user. First the following import statement is needed in file my-dialog.component.ts:

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

Furthermore you need to make sure that Inject is imported from the @angular/core package. Now we’re able to use the following injection syntax as a second parameter for the class constructor.

@Inject(MD_DIALOG_DATA) public data: string

Now the data property is available and can be used to access the string value and include that value in the output:

<strong>{{data}}</strong>

Tooltip

Next, let’s take a look at Tooltips from the Angular Material library. To make Tooltips available in your Angular application you need to import the corresponding Angular Material module in app.module.ts first:

import {MdTooltipModule} from '@angular/material';

Furthermore add MdTooltipModule to the array which is assigned to the imports property in @NgModule. Next, we’re creating a new component for the Tooltip demo

$ ng g component TooltipDemo

Again four new files are added to the project containing the default implementation of an Angular component. Open file tooltip-demo.component.html and replace the default content with the following code:

<md-card class="card1"> <md-card-header> <md-card-title><h1>Tooltip Demo</h1></md-card-title> </md-card-header> <hr> <md-card-content> <span mdTooltip="This is the Tooltip!">This text has a tooltip!</span> </md-card-content> </md-card>

Furthermore add the corresponding element to app.component.html:

<div style="text-align:center"> <app-dialog-demo></app-dialog-demo> <app-tooltip-demo></app-tooltip-demo> </div>

Positioning Of ToolTips

The default position of the tooltip is at the bottom of the element to which the mdTooltip directive is applied. This default behavior can be changed by using the mdTooltipPosition directive in the following way:

<span mdTooltip="This is the Tooltip!" mdTooltipPosition="above">This text has a tooltip!</span>

In this example we’re assigning the string value “above” to the directive to specify that the tooltip should by displayed above the element. The result should now look like the following:

Snackbar

Snackbars are an easy way to display notifications in your application. To make use of Snackbars import the MdSnackBarModule in your main application module, like we did it for the other modules before.

import {MdSnackBarModule} from '@angular/material';

Having imported this module you can inject the MdSnackBar service in your components. Let’s add another component to our project:

$ ng g component SnackbarDemo

Having generated the new component files, don’t forget to include it in app.component.html as well:

<div style="text-align:center"> <app-dialog-demo></app-dialog-demo> <app-tooltip-demo></app-tooltip-demo> <app-snackbar-demo></app-snackbar-demo> </div>

Displaying A Snackbar

Basically there are two service methods available you can use to display a Snackbar to the user:

open : This methods opens a Snackbar with a message text and a custom action label.

: This methods opens a Snackbar with a message text and a custom action label. openFormComponent: This methods creates and dispatches a Snackbar. It shows the content of a custom component which is passed as in as a parameter.

Let’s try out the open method. As before we’re creating a new component in our application to contain the code which is needed for the Snackbar demo:

$ ng g component SnackbarDemo

Insert the following template code in file snackbar-demo.component.html:

<md-card class="card1"> <md-card-header> <md-card-title><h1>Snackbar Demo</h1></md-card-title> </md-card-header> <hr> <md-card-content> <button md-raised-button (click)="openSnackbar()">Open Snackbar</button> </md-card-content> </md-card>

Again, we’re including a button which the user can use to open display the snackbar at the bottom of the browser window. The click event of this button is connected to the openSnackbar() event handler method which needs to be implemented in the component class:

import { Component, OnInit } from '@angular/core'; import {MdSnackBar} from '@angular/material'; @Component({ selector: 'app-snackbar-demo', templateUrl: './snackbar-demo.component.html', styleUrls: ['./snackbar-demo.component.css'] }) export class SnackbarDemoComponent implements OnInit { constructor(public snackBar: MdSnackBar) { } ngOnInit() { } openSnackbar() { this.snackBar.open("This is the SnackBar Message", "Got it!"); } }

Now you should be able to see the following result after pressing the button:

You can supply the open method with a third parameter which is an configuration object of type MdSnackBarConfig . E.g. you can use the configuration property duration to specify that the Snackbar is closed after a certain amount of milliseconds automatically. Change the implementation of method openSnackbar() to the following to automatically close the Snackbar after 1000 milliseconds.

openSnackbar() { this.snackBar.open("This is the SnackBar Message", "Got it!", { duration: 1000 }); }

Furthermore the Snackbar service let’s you subscribe to Observables by using the following methods:

afterDismissed : Gets an observable that is notified when the snack bar is finished closing.

: Gets an observable that is notified when the snack bar is finished closing. afterOpened : Gets an observable that is notified when the snack bar has opened and appeared.

: Gets an observable that is notified when the snack bar has opened and appeared. onAction: Gets an observable that is notified when the snack bar action is called.

To subscribe to one of these Observables you can use the same approach as seen before in the Dialog section of this tutorial.