How to Programmatically Open an Angular Modal Using TypeScript in Angular 2+
You can programmatically open an angular modal by injecting the MatDialog service from Angular Material and calling its open() method with a component class and optional configuration object.
Programmatically opening modals in Angular 2+ applications requires a service-based approach rather than template-based directives. The Angular Material library provides the official MatDialog service for creating modal dialogs, as demonstrated in the angular/angular repository's developer tools implementation. This approach works across all Angular versions from Angular 2 through the latest releases.
Understanding MatDialog for Programmatic Modal Control
The MatDialog service provides the primary API for programmatically opening angular modals. Unlike template-driven approaches that rely on structural directives, this service allows you to open dialogs imperatively from TypeScript code, making it ideal for handling user interactions that trigger modals dynamically.
According to the source code in devtools/src/app/demo-app/todo/app-todo.component.ts (lines 64-70), the implementation follows a three-step pattern: inject the service, define the dialog component, and call open() with configuration options.
Step 1: Create the Dialog Content Component
Before you can open a modal programmatically, you must define a component that contains the dialog's UI and logic. This component receives data through the MAT_DIALOG_DATA injection token and can close itself using MatDialogRef.
As implemented in devtools/src/app/demo-app/todo/dialog.component.ts (lines 27-46), a typical dialog component looks like this:
import {Component, inject} from '@angular/core';
import {
MAT_DIALOG_DATA,
MatDialogRef,
MatDialogTitle,
MatDialogContent,
MatDialogActions,
MatDialogClose,
} from '@angular/material/dialog';
import {MatInputModule} from '@angular/material/input';
import {MatFormFieldModule} from '@angular/material/form-field';
import {FormsModule} from '@angular/forms';
export interface DialogData {
name: string;
animal: string;
}
@Component({
selector: 'app-dialog',
templateUrl: 'dialog.component.html',
imports: [
MatDialogTitle,
MatDialogContent,
MatFormFieldModule,
MatInputModule,
FormsModule,
MatDialogActions,
MatDialogClose,
],
})
export class DialogComponent {
public dialogRef = inject<MatDialogRef<DialogComponent>>(MatDialogRef);
public data = inject<DialogData>(MAT_DIALOG_DATA);
onNoClick(): void {
this.dialogRef.close();
}
}
This component demonstrates the essential pattern: inject MatDialogRef to control the dialog instance and MAT_DIALOG_DATA to receive input parameters.
Step 2: Inject MatDialog and Programmatically Open the Modal
With the dialog component defined, you can now programmatically open the modal from any host component by injecting the MatDialog service and calling its open() method.
The implementation in devtools/src/app/demo-app/todo/app-todo.component.ts (lines 64-70) demonstrates this pattern:
import {Component, inject} from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {DialogComponent, DialogData} from './dialog.component';
@Component({
selector: 'app-todo-demo',
templateUrl: './app-todo.component.html',
})
export class AppTodoComponent {
name = '';
animal = '';
private readonly dialog = inject(MatDialog);
openDialog(): void {
const dialogRef = this.dialog.open(DialogComponent, {
width: '250px',
data: {name: this.name, animal: this.animal} as DialogData,
});
dialogRef.afterClosed().subscribe((result) => {
console.log('The dialog was closed');
if (result) {
this.animal = result;
}
});
}
}
The open() method accepts two parameters: the component class to render inside the modal, and an optional configuration object. It returns a MatDialogRef instance that allows you to monitor when the dialog closes via the afterClosed() observable.
Alternative Injection Pattern: Constructor Injection
While the example above uses the modern inject() function introduced in Angular 14, you can also use traditional constructor injection for Angular 2 compatibility:
export class AppTodoComponent {
constructor(private dialog: MatDialog) {}
openDialog(): void {
const dialogRef = this.dialog.open(DialogComponent, {
width: '250px',
data: {name: this.name, animal: this.animal}
});
// ... handle result
}
}
Both approaches are functionally equivalent. The inject() syntax offers better tree-shaking and works outside constructors, while constructor injection remains the standard pattern for Angular 2 through Angular 13.
Configuration Options for MatDialog.open()
When you programmatically open an angular modal, you can customize its behavior through the configuration object passed to open():
- width and height: Define explicit dimensions (e.g.,
'250px','50vw') - data: Pass an object to the dialog component via
MAT_DIALOG_DATA - disableClose: Set to
trueto prevent closing via backdrop click or Escape key - panelClass: Apply custom CSS classes to the dialog container
- autoFocus: Control focus behavior when the dialog opens
Example with multiple options:
const dialogRef = this.dialog.open(DialogComponent, {
width: '400px',
height: '300px',
disableClose: true,
panelClass: 'custom-dialog',
data: {name: this.name, animal: this.animal}
});
Summary
- Programmatically open an angular modal by injecting the
MatDialogservice and callingopen()with a component class and optional configuration. - Create a dedicated dialog component that injects
MatDialogReffor closing the modal andMAT_DIALOG_DATAfor receiving input parameters. - Subscribe to
afterClosed()on the returnedMatDialogRefto handle results when the user dismisses the dialog. - Use either the modern
inject()function or traditional constructor injection depending on your Angular version. - Reference the implementation in
devtools/src/app/demo-app/todo/app-todo.component.tsanddevtools/src/app/demo-app/todo/dialog.component.tsfor production-ready examples.
Frequently Asked Questions
Can I programmatically open an angular modal without Angular Material?
Yes, though Angular Material's MatDialog is the officially recommended approach. You can build custom modals using the CDK Overlay package (@angular/cdk/overlay), which MatDialog itself uses internally. This requires manually creating an overlay, attaching a portal with your component, and managing focus and backdrop clicks yourself.
How do I pass data to a programmatically opened angular modal?
Pass a data object in the configuration parameter of open(). Inside your dialog component, inject MAT_DIALOG_DATA to access this information. For example: public data = inject<DialogData>(MAT_DIALOG_DATA). Changes to this data inside the dialog do not automatically propagate back to the parent; use MatDialogRef.close(result) to return modified data.
What is the difference between MatDialogRef and MatDialog?
MatDialog is the service you inject to open new dialogs programmatically. It provides the open() method and manages the global dialog state. MatDialogRef is the reference returned by open() that represents a specific dialog instance. Use MatDialogRef to close that specific dialog, subscribe to afterClosed(), or update its position programmatically.
How do I prevent users from closing a modal by clicking the backdrop?
Set disableClose: true in the configuration object passed to open(). This disables both backdrop clicks and the Escape key as closing mechanisms. When using this option, ensure you provide an explicit close button inside your dialog component that calls MatDialogRef.close() so users can still dismiss the modal intentionally.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →