Click with Confidence — Create an Angular Decorator for Confirmations
In modern web applications, protecting users from accidental clicks is essential. Whether it’s deleting data, submitting sensitive information, or triggering irreversible operations — users should always confirm their intent.
In Angular, this is usually handled with a MatDialog
. But repeating the same confirmation logic across multiple components gets messy fast. What if you could abstract that away into a simple, reusable decorator?
That’s what we’ll build today: a @ConfirmAction
decorator powered by Angular Material. It will improve code readability and deliver a better UX — without cluttering every method.
💡 Why a @ConfirmAction
Decorator?
Imagine this: you have delete buttons across different components. Each one pops up a MatDialog
asking the user to confirm. The logic looks almost identical everywhere.
What if you could just write this:
@ConfirmAction()
deleteUser() {
// delete logic
}
✅ Less repetition
✅ Centralized confirmation logic
✅ Cleaner, DRYer code
That’s the goal.
🧰 Prerequisites
Make sure your Angular project is set up with:
Angular CLI v14+
Angular Material
If not:
ng add @angular/material
🏗 Step 1: Create a Reusable Confirmation Dialog
First, we need a simple dialog component that will ask users to confirm their action.
confirm-dialog.component.ts
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-confirm-dialog',
template: `
<h1 mat-dialog-title>Confirm</h1>
<div mat-dialog-content>
<p>{{ data.message || 'Are you sure you want to proceed?' }}</p>
</div>
<div mat-dialog-actions>
<button mat-button (click)="dialogRef.close(false)">Cancel</button>
<button mat-button color="warn" (click)="dialogRef.close(true)">Confirm</button>
</div>
`
})
export class ConfirmDialogComponent {
constructor(
public dialogRef: MatDialogRef<ConfirmDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { message: string }
) {}
}
🔮 Step 2: Build the @ConfirmAction
Decorator
Here’s where the magic happens.
confirm-action.decorator.ts
import { MatDialog } from '@angular/material/dialog';
import { ConfirmDialogComponent } from './confirm-dialog.component';
export function ConfirmAction(message = 'Are you sure you want to proceed?') {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
const dialog: MatDialog = this.dialog || this.injector?.get(MatDialog);
if (!dialog) {
console.error('MatDialog not found. Make sure it is injected properly.');
return;
}
const ref = dialog.open(ConfirmDialogComponent, {
data: { message }
});
const confirmed = await ref.afterClosed().toPromise();
if (confirmed) {
return originalMethod.apply(this, args);
}
};
return descriptor;
};
}
🎮 Step 3: Use the Decorator in a Component
Here’s how easy it becomes to apply confirmations anywhere:
import { Component } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmAction } from './confirm-action.decorator';
@Component({
selector: 'app-user-actions',
template: `<button mat-button (click)="deleteUser()">Delete</button>`
})
export class UserActionsComponent {
constructor(public dialog: MatDialog) {}
@ConfirmAction('This action will delete the user. Are you sure?')
deleteUser() {
console.log('User deleted!');
// your deletion logic here
}
}
🎯 Final Result
Every time deleteUser()
is called:
A confirmation dialog opens.
The app waits for user input.
The method runs only if the user confirms.
👉 No more cluttering methods with repeated dialog logic!
🔧 Bonus Tips
Customize the dialog with icons, styles, or i18n support.
Inject
MatDialog
via a shared service if your context doesn’t have it directly.Extend this pattern for:
role-based prompts
multi-step confirmations
undo actions
🏁 Conclusion
With a simple @ConfirmAction
decorator, you can build cleaner, safer, and more user-friendly Angular applications.
It’s a small abstraction, but it saves developers from repetitive boilerplate — and helps users click with confidence.
Let’s stay connected across all platforms!
Instagram: @angular_development
Facebook: Learn Angular
Software Dev: TopMate.io
Threads: @angular_development
LinkedIn: InfoWeb Technologies
Training Portal: Beginner to Pro Training
Newsletter: CodeForWeb Substack
Pinterest: Tech Nerd Life
Portfolio: InfoWeb Technologies
Projects: Next Generation Projects
📧 For business inquiries:
Feel free to contact us at softwaredeveloper321@protonmail.com