Angular Material is a UI component library that provides modern, responsive, and accessible UI elements for Angular applications. One of its most powerful features is the mat-dialog
service, which enables developers to create modal dialogs for user interactions such as confirmations, form inputs, alerts, and custom content popups.
In this tutorial, you’ll learn how to master the mat-dialog
component with real-world examples. We’ll walk through creating a dialog, passing data to it, receiving results, and building reusable dialog components with various practical use cases.
Whether you’re building a confirmation popup, a form inside a modal, or a complex interactive dialog, this guide will help you use Angular Material dialogs effectively.
Prerequisites
Before you begin, make sure you have the following installed on your system:
-
Node.js (v18 or later)
-
Angular CLI (v20 or later)
-
Basic understanding of Angular components, services, and modules
You can check your versions by running:
node -v
ng version
If you don’t have Angular CLI installed:
npm install -g @angular/cli
Setting Up the Angular Project
1. Create a new Angular app
ng new angular-material-dialog-example
When prompted:
-
Add Angular routing: Yes
-
Choose stylesheet format: SCSS (or your preference)
Navigate into the project folder:
cd angular-material-dialog-example
2. Install Angular Material
ng add @angular/material
Select a theme (e.g., Indigo/Pink) and enable animations when prompted.
This will automatically:
-
Add
@angular/material
,@angular/cdk
, and@angular/animations
-
Import a prebuilt theme into
angular.json
-
Enable animations in
app.module.ts
3. Run the App
Make sure everything is working by running:
ng serve
Visit http://localhost:4200/
in your browser. You should see the default Angular app homepage.
Creating and Opening a Dialog Component
In Angular Material, dialogs are typically standalone components that are launched via the MatDialog
service. In this section, we’ll create a basic dialog and show how to open it from a button click in the main component.
Step 1: Generate the Dialog Component
We’ll generate a separate component for the dialog content.
ng generate component confirm-dialog
This will create the confirm-dialog
component in the src/app/
directory.
Step 2: Design the Confirm Dialog Component
Edit confirm-dialog.ts
to make it a simple confirmation dialog:
import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-confirm-dialog',
imports: [
CommonModule,
MatDialogModule,
MatButtonModule
],
templateUrl: './confirm-dialog.html',
styleUrl: './confirm-dialog.scss'
})
export class ConfirmDialog {
constructor(
public dialogRef: MatDialogRef<ConfirmDialog>,
@Inject(MAT_DIALOG_DATA) public data: { message: string }
) { }
onConfirm(): void {
this.dialogRef.close(true);
}
onCancel(): void {
this.dialogRef.close(false);
}
}
Then edit the confirm-dialog.html
:
<h2 mat-dialog-title>Confirm</h2>
<mat-dialog-content>{{ data.message }}</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button (click)="onCancel()">Cancel</button>
<button mat-raised-button color="primary" (click)="onConfirm()">Confirm</button>
</mat-dialog-actions>
Step 3: Open the Dialog from AppComponent
Edit app.ts
to open the dialog when a button is clicked:
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { RouterOutlet } from '@angular/router';
import { ConfirmDialog } from './confirm-dialog/confirm-dialog';
@Component({
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.html',
styleUrl: './app.scss'
})
export class App {
constructor(private dialog: MatDialog) { }
openConfirmDialog(): void {
const dialogRef = this.dialog.open(ConfirmDialog, {
width: '350px',
data: { message: 'Are you sure you want to proceed?' }
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
console.log('User confirmed');
} else {
console.log('User cancelled');
}
});
}
}
And update the app.html
to include a trigger button:
<div style="text-align:center; margin-top: 100px;">
<h1>Angular Material Dialog Example</h1>
<button mat-raised-button color="primary" (click)="openConfirmDialog()">
Open Confirm Dialog
</button>
</div>
You now have a working confirmation dialog! Clicking the button opens the dialog, and the response is logged in the console.
Adding a Form Inside a Dialog
We’ll create a new dialog component that contains a simple form with fields like name and email, and then open it from the main component.
Step 1: Generate the Form Dialog Component
ng generate component form-dialog
This creates the form-dialog
component inside src/app/
.
Step 2: Create the Form in the Dialog Component
form-dialog.ts
:
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'app-form-dialog',
imports: [
CommonModule,
ReactiveFormsModule,
MatDialogModule,
MatFormFieldModule,
MatInputModule
],
templateUrl: './form-dialog.html',
styleUrl: './form-dialog.scss'
})
export class FormDialog {
form: FormGroup;
constructor(
private fb: FormBuilder,
private dialogRef: MatDialogRef<FormDialog>
) {
this.form = this.fb.group({
name: ['', Validators.required],
email: ['', [Validators.required, Validators.email]]
});
}
onSubmit(): void {
if (this.form.valid) {
this.dialogRef.close(this.form.value);
}
}
onCancel(): void {
this.dialogRef.close();
}
}
form-dialog.html
:
<h2 mat-dialog-title>Enter Your Details</h2>
<mat-dialog-content [formGroup]="form">
<mat-form-field appearance="fill" class="w-full">
<mat-label>Name</mat-label>
<input matInput formControlName="name" />
</mat-form-field>
<mat-form-field appearance="fill" class="w-full">
<mat-label>Email</mat-label>
<input matInput formControlName="email" />
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button (click)="onCancel()">Cancel</button>
<button
mat-raised-button
color="primary"
(click)="onSubmit()"
[disabled]="form.invalid"
>
Submit
</button>
</mat-dialog-actions>
And style it a bit in form-dialog.scss
(optional):
mat-form-field {
width: 100%;
margin-bottom: 12px;
}
Step 3: Open the Form Dialog from AppComponent
Update app.ts
:
import { FormDialog } from './form-dialog/form-dialog';
openFormDialog(): void {
const dialogRef = this.dialog.open(FormDialog, {
width: '400px'
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
console.log('Form Data:', result);
}
});
}
Update app.html
:
<!-- Add a second button -->
<button mat-raised-button color="accent" (click)="openFormDialog()">
Open Form Dialog
</button>
Now, when you click the "Open Form Dialog" button, a modal form will appear. After submitting valid input, it will close and return the form data to the main component.
Reusable Dialog Component Tips
Instead of writing a new dialog for every use case, you can build flexible, reusable dialogs by designing them to accept dynamic data and return results.
Example: Reusable Confirmation Dialog
We'll refactor the ConfirmDialogComponent
to be configurable and reusable across different parts of the app.
Step 1: Define a Confirmation Dialog Data Model
Create a file called confirm-dialog.model.ts
:
export interface ConfirmDialogData {
title?: string;
message: string;
confirmText?: string;
cancelText?: string;
}
This lets you provide default or custom dialog content dynamically.
Step 2: Update ConfirmDialogComponent
to Use the Model
Modify confirm-dialog.ts
:
import { CommonModule } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { ConfirmDialogData } from './confirm-dialog.model';
@Component({
selector: 'app-confirm-dialog',
imports: [
CommonModule,
MatDialogModule,
MatButtonModule
],
templateUrl: './confirm-dialog.html',
styleUrl: './confirm-dialog.scss'
})
export class ConfirmDialog {
constructor(
public dialogRef: MatDialogRef<ConfirmDialog>,
@Inject(MAT_DIALOG_DATA) public data: ConfirmDialogData
) { }
onConfirm(): void {
this.dialogRef.close(true);
}
onCancel(): void {
this.dialogRef.close(false);
}
}
Update confirm-dialog.html
:
<h2 mat-dialog-title>{{ data.title || 'Confirm' }}</h2>
<mat-dialog-content>{{ data.message }}</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-button (click)="onCancel()">
{{ data.cancelText || 'Cancel' }}
</button>
<button mat-raised-button color="primary" (click)="onConfirm()">
{{ data.confirmText || 'Confirm' }}
</button>
</mat-dialog-actions>
Step 3: Create a Centralized Dialog Service (Optional, but Recommended)
This service helps you reuse the confirmation dialog anywhere easily.
ng generate service dialog
Then in dialog.ts
:
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmDialogData } from './confirm-dialog/confirm-dialog.model';
import { Observable } from 'rxjs';
import { ConfirmDialog } from './confirm-dialog/confirm-dialog';
@Injectable({
providedIn: 'root'
})
export class Dialog {
constructor(private dialog: MatDialog) { }
confirm(data: ConfirmDialogData): Observable<boolean> {
const dialogRef = this.dialog.open(ConfirmDialog, {
width: '350px',
data
});
return dialogRef.afterClosed();
}
}
Step 4: Use the Dialog Anywhere with One Line
In any component (e.g. AppComponent
), use the dialog like this:
import { Dialog } from './dialog';
constructor(private dialogService: Dialog) {}
showDeleteConfirm(): void {
this.dialogService.confirm({
title: 'Delete Item',
message: 'Are you sure you want to delete this item?',
confirmText: 'Delete',
cancelText: 'Keep'
}).subscribe(result => {
if (result) {
console.log('Item deleted');
} else {
console.log('Action canceled');
}
});
}
And in app.component.html
:
<button mat-raised-button color="warn" (click)="showDeleteConfirm()">
Open Reusable Confirm Dialog
</button>
Benefits of This Approach
-
DRY (Don’t Repeat Yourself) principle
-
Centralized dialog logic for better maintainability
-
Easy to unit test
-
Flexible for multiple use cases: delete, logout, overwrite, etc.
Customizing mat-dialog Width, Height, Animations, and Styling
Angular Material’s MatDialog
is highly configurable using the MatDialogConfig
object, which lets you control the dialog's dimensions, position, backdrop, animations, and custom styles.
1. Set Custom Width and Height
You can define the width and height directly when opening a dialog.
Example:
this.dialog.open(FormDialogComponent, {
width: '500px',
height: '400px', // optional
data: { /* ... */ }
});
✅ Tip: Use CSS units like
px
,vw
,vh
,%
, or evenauto
.
2. Set Custom Position
You can place dialogs in specific screen positions using position
.
this.dialog.open(FormDialogComponent, {
width: '400px',
position: {
top: '50px',
right: '50px'
}
});
3. Control Backdrop Behavior
-
Disable closing by clicking outside (backdrop click):
this.dialog.open(FormDialogComponent, {
disableClose: true
});
- Disable or remove the backdrop entirely:
this.dialog.open(FormDialogComponent, {
hasBackdrop: false
});
4. Add Custom Dialog Animations
While Angular Material doesn’t expose dialog entrance/exit animations directly, you can animate the dialog content using Angular’s @angular/animations
.
Example: Add a fade-in animation
Step 1 – Import animation modules in the component:
import {
trigger,
transition,
style,
animate
} from '@angular/animations';
Step 2 – Add animation metadata to the component:
@Component({
...,
animations: [
trigger('fadeIn', [
transition(':enter', [
style({ opacity: 0 }),
animate('250ms ease-in', style({ opacity: 1 }))
])
])
]
})
Step 3 – Apply it in the dialog HTML root element:
<div [@fadeIn]>
<!-- Your dialog content -->
</div>
🎯 You can also use
scale
,slideIn
, or custom animations depending on your app’s design needs.
5. Style the Dialog with Custom CSS
Material dialogs have the wrapper class mat-dialog-container
, but you can target your class for better isolation.
Option A – Use panelClass
to add a custom class:
this.dialog.open(FormDialogComponent, {
panelClass: 'custom-dialog-container'
});
Option B – Add this to styles.scss
or component styles:
::ng-deep .custom-dialog-container {
border-radius: 12px;
padding: 24px;
background: #f9f9f9;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}
⚠️ ::ng-deep
is deprecated but still works. For full encapsulation, move styles to a global stylesheet or use the ViewEncapsulation feature.None if necessary.
Combine Everything
Here’s a sample config that applies custom width, disables outside click, adds a CSS class, and sets position:
this.dialog.open(FormDialogComponent, {
width: '450px',
position: { top: '100px' },
disableClose: true,
panelClass: 'custom-dialog-container',
data: { /* ... */ }
});
Conclusion
Angular Material's mat-dialog
is a powerful and flexible tool for creating modal dialogs in Angular applications. Whether you're building simple confirmation popups or complex forms, MatDialog
provides the structure, accessibility, and theming capabilities to do it all — cleanly and efficiently.
In this tutorial, you learned how to:
-
Set up Angular Material and integrate dialogs into your project
-
Create and open dialogs using the
MatDialog
service -
Pass data to and receive results from dialogs
-
Add forms inside dialogs for user input
-
Customize dialog width, height, position, and backdrop behavior
-
Animate and style dialogs for a more polished UI
-
Build reusable dialogs using a central service and configuration model
These techniques allow you to reuse dialog components, standardize dialog interactions, and maintain a clean codebase as your Angular application scales.
Key Takeaways
-
Use
MatDialog
to handle modal dialogs in Angular Material. -
Always separate dialogs into their components for reusability.
-
Pass data using
MAT_DIALOG_DATA
, and return values viaMatDialogRef.afterClosed()
. -
Customize appearance using
panelClass
,position
,width
, and custom animations. -
Abstract confirmation dialogs using a dialog service to reduce repetition.
You can get the full source code on our GitHub.
If you don’t want to waste your time designing your front-end or your budget to spend by hiring a web designer, then Angular Templates is the best place to go. So, speed up your front-end web development with premium Angular templates. Choose your template for your front-end project here.
That's just the basics. If you need more deep learning about Angular, you can take the following cheap course:
- Angular Crash Course - Learn Angular And Google Firebase
- Real-time Communication using Socket. IO 3.x and Angular 11.x
- Angular Progressive Web Apps (PWA) MasterClass & FREE E-Book
- Enterprise-Scale Web Apps with Angular
- Angular Forms In Depth (Angular 20)
- Microservicios Spring Boot y Angular MySql Postgres
-
Angular Developer Interview Questions Practice Test Quiz
Thanks!