'Angular conditional confirm dialog - How to avoid writing redundant code?
I need a simple confirm dialog where the user has to either click "Yes" or "No". I wrote a simple dialog component to do this with the following code:
confirmation-dialog-component.ts:
import { Component, Inject } from "@angular/core";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
@Component({
selector: "app-confirmation-dialog",
templateUrl: "./confirmation-dialog.component.html",
styleUrls: ["./confirmation-dialog.component.scss"],
})
export class ConfirmationDialogComponent {
constructor(
public dialogRef: MatDialogRef<ConfirmationDialogComponent>,
@Inject(MAT_DIALOG_DATA) public text: string,
) {}
onNoClick(): void {
this.dialogRef.close(false);
}
onYesClick(): void {
this.dialogRef.close(true);
}
}
confirmation-dialog-component.html:
<div class="dialog-title">
<h2>Confirmation</h2>
<button mat-icon-button class="close-button" (click)="onNoClick()" tabindex="-1">
<mat-icon>close</mat-icon>
</button>
</div>
<div mat-dialog-content>
<span>{{ text }}</span>
</div>
<mat-dialog-actions align="end">
<button type="button" mat-button color="accent" (click)="onNoClick()">
No
</button>
<button type="submit" mat-raised-button color="primary" (click)="onYesClick()">
Yes
</button>
</mat-dialog-actions>
If I want the user to confirm something, I can use the dialog like this:
const confirmDialogRef = this.dialog.open(ConfirmationDialogComponent, {
data: "Do you really want to do this?",
});
confirmDialogRef.afterClosed().subscribe((confirmResult) => {
if (confirmResult === true) {
// User confirmed the dialog
}
});
Now I have a situation where I only need to show the confirmation dialog under certain conditions. Back when I was still writing WinForms applications in C#, I could easily show a confirmation dialog like this:
if (MessageBox.Show("Do you really want to do this?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
// User confirmed the dialog
}
This would allow me to easily skip showing the confirmation dialog under certain conditions:
if (showConfirmationDialog == false || MessageBox.Show("Do you really want to do this?", "Confirmation", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
// Continue
}
How can I do something similar with my own confirmation dialog? I cannot just show it under certain conditions because if I have to show it, I need to move my code which should be executed if the user clicks "Yes" into the subscribe. However, if the condition is true so I do not need to show the dialog, I do not need the subscribe. This forces me to have two places in my code where I need to write what should happen after the user clicks "Yes" or if the condition is true. Is there a more elegant way to do this?
Solution 1:[1]
One way would be to use an observable stream to track your condition and show/not show the dialog based on that.
Say, for instance, you are calling a function showDialog() that returns a boolean/promise/observable, that then decides whether or not to show the dialog, you can create an observable from that:
showDialog(): boolean{
let showDialog = true
// Determine whether to show
return showDialog
}
Then create an observable from that and pipe it down the stream.
// Imports
import {of} from 'rxjs'
// somewhere in your class implementation
of(showDialog())
.pipe(
mergeMap((show: boolean): [boolean, any] =>{
if(show) return [of(show), this.openDialog()]
else return [of(show), {}]
})
)
.subscribe(([dialogWasShown, result])=>{
if(dialogWasShown){
// do something with the result
}
else {
// do something else
}
})
In the above case, you have your condition determining whether or not to show the dialog.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Laurence Ininda |
