In this post, we’ll learn how to open a Modal Popup Dialog in Angular 9/8 application using the Material UI library.
Angular Material is a UI library which provides a number of components. It works great with the Angular framework and helps in developing awesome applications. This UI library is based on Material design principals which add on user experience a lot!
Here we will discuss How to add and use Modals as we have seen in Bootstrap projects. But in an Angular project, we’ll use the Material library to implement Modals. Like any other library, Material Modals can communicate with data which we can pass from parent and in return, the Modals can return back the data on close events.
Let’s get started!
# Setup Angular CLI
We’ll create Angula project in the latest version. Make sure you have updated the Angular CLI tool by running below npm
command in the terminal
$ npm install -g @angular/cli
# Create an Angular Project
Execute below ng
command to create an Angular project in latest version 9.1.3. But this tutorial is compatible with previous version 7,6,5 and 4
$ ng new angular-material-modals
$ cd angular-material-modals
# Install Angular Material in project
After version 8, Angular Material package can be installed by executing the following ng
command. For configuration, it will ask a few questions related to the theme, browser animations etc
$ ng add @angular/material
Answer questions
? Choose a prebuilt theme name, or "custom" for a custom theme: Indigo/Pink
? Set up global Angular Material typography styles? Yes
? Set up browser animations for Angular Material? Yes
Now our Angular project is ready to use Material components.
# Import Material Modules
The Material UI library provides a wide variety of components, so we need to import the API module of the component we are going to use in the App module.
Here as we'll be using the Modal Dialog so we need to import MatDialogModule
. Also, we'll have a form with Inputs and Buttons, so also import the FormsModule
, MatFormFieldModule
, MatInputModule
, and MatButtonModule
in the app.module.ts file as shown below
// app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { MyModalComponent } from './modals/my-modal/my-modal.component'; import { FormsModule } from '@angular/forms'; import { MatDialogModule } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; @NgModule({ declarations: [ AppComponent, MyModalComponent ], imports: [ BrowserModule, AppRoutingModule, BrowserAnimationsModule, FormsModule, MatDialogModule, MatFormFieldModule, MatInputModule, MatButtonModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
# Create Modal Component
The Modal can have its own component which will act a modal container. Run the following ng generate
command to create a my-modal
component in the modals folder.
$ ng generate component modals/my-modal
Now open the app>modals>my-modal.component.ts file and place following code in it
// my-modal.component.ts
import { Component, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
@Component({
selector: 'app-my-modal',
templateUrl: './my-modal.component.html',
styleUrls: ['./my-modal.component.css']
})
export class MyModalComponent {
food: string;
constructor(
public dialogRef: MatDialogRef<MyModalComponent>,
@Inject(MAT_DIALOG_DATA) public data: any) { }
onNoClick(): void {
this.dialogRef.close({
food: this.food
});
}
}
How to Get Data passed from a parent component in Modal?
Data object passed from parent component will be available in the data
property. We can also define a type to this data but to keep this tutorial simple we have not created any model or interface.
Update the my-modal.component.html file with below template:
<h1 mat-dialog-title>You are from {{data.name}}</h1>
<div mat-dialog-content>
<p>What's your favorite city?</p>
<mat-form-field>
<mat-label>Favorite City</mat-label>
<input matInput [(ngModel)]="data.city">
</mat-form-field>
<p>Your favorite food?</p>
<mat-form-field>
<mat-label>Favorite Food</mat-label>
<input matInput [(ngModel)]="food">
</mat-form-field>
</div>
<div mat-dialog-actions>
<button mat-button (click)="onNoClick()">Get Food</button>
<button mat-button [mat-dialog-close]="data.city" cdkFocusInitial>Get City</button>
</div>
How to send back data from Modal to parent component?
There are two methods to send-back data from Modal component to parent component:
1) Use [mat-dialog-close]
property
This property can have an Object to pass the data to the parent. On clicking on a button with this property will also close the modal.
2) Use close()
method
The MatDialogRef
class provides the close()
method which we called in the onNoClick()
method in the my-modal.component.ts file above. The close()
method will pass data object and also close the modal.
# Open Modal from App Component
To open the modal we will update the app.componet.html file to have the following template
<ol>
<li>
<mat-form-field>
<mat-label>Where do you stay?</mat-label>
<input matInput [(ngModel)]="name">
</mat-form-field>
</li>
<li>
<button mat-raised-button (click)="openDialog()">Pick city or food</button>
</li>
<li *ngIf="city">
You chose: <i>{{city}}</i>
</li>
<li *ngIf="food_from_modal">
I love {{food_from_modal}}
</li>
</ol>
Update the app.component.ts component class with below code
// app.component.ts
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MyModalComponent } from './modals/my-modal/my-modal.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'angular-material-modals';
city: string;
name: string;
food_from_modal: string;
constructor(public dialog: MatDialog) { }
openDialog(): void {
const dialogRef = this.dialog.open(MyModalComponent, {
width: '250px',
data: { name: this.name, animal: this.city }
});
dialogRef.afterClosed().subscribe(result => {
console.log('The dialog was closed', result);
this.city = result;
this.food_from_modal = result.food;
});
}
}
How to Pass data from parent component to Modal?
The Modal can be opened by calling the open()
method available in the MatDialog
class. This method takes first argument as the Modal component and second takes configuration with data
property.
We can pass data
using the data property.
How to get data in the parent component passed by Modal?
We need to subscribe to the afterClosed()
method available in the MatDialog
class, which return the object passed by modal after it closes.
Now you can run your Angular project by hitting $ ng serve --open
to see it working.
Conclusion: Modals in an application plays an important role to simplify the user experiences. We have used many time the Modals available in the Bootstrap framework, but Angular application can also use Material based Dialogs in form of Modals.