Reputation: 780
I have created a modal as a separate component in my angular project as the following:
HTML:
<div mat-dialog-title>
{{title}}
</div>
<div mat-dialog-content>
<p>{{message}}</p>
</div>
<div mat-dialog-actions>
<button mat-button color="primary" (click)="confirm()">{{btnOkText}}</button>
<button mat-button (click)="decline()" cdkFocusInitial>{{btnCancelText}}</button>
</div>
TS:
export class ConfirmDialogComponent implements OnInit {
title!: string;
message!: string;
btnOkText!: string;
btnCancelText!: string;
constructor(
public dialogRef: MatDialogRef<ConfirmDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: ConfirmDialogModel) {
// Update view with given values
this.title = data.title;
this.message = data.message;
this.btnOkText = data.btnOkText;
this.btnCancelText = data.btnCancelText;
}
ngOnInit(): void {
}
confirm() {
// Close the dialog, return true
this.dialogRef.close(true);
}
decline() {
// Close the dialog, return false
this.dialogRef.close(false);
}
}
/**
* Class to represent confirm dialog model.
*
* It has been kept here to keep it as part of shared component.
*/
export class ConfirmDialogModel {
constructor(
public title: string,
public message: string,
public btnOkText: string,
public btnCancelText: string) {
}
}
I created a service that is root injected and put in a method that initialize and open the dialog box as the following:
confirmDialog(): void {
const title = 'Confirmation';
const message = 'Are you sure you want to do this?';
const btnOkText = 'Ok';
const btnCancelText = 'Cancel';
const dialogData = new ConfirmDialogModel(title, message, btnOkText, btnCancelText);
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
maxWidth: "400px",
data: dialogData
});
dialogRef.afterClosed().subscribe(dialogResult => {
dialogResult;
});
}
If I console.log(dialogResult)
I will get the right result (true/false)
All of that is good, however, I want to turn this dialogResult
into an observable where any component calls my confirm service, gets to see the dialogResult
then do an action based on it.
Example:
I have a home component and I injected my confirmService into it
constructor(private confirmService : ConfirmService) {}
then, in home.html, I created a button with (click) event like the following:
<button mat-raised-button color="primary" (click)="confirm()">Confirm</button>
The function confirm() is like the following:
confirm() {
this.confirmService.confirmDialog();
}
I want to be able to subscribe to the confirmDialog()
and get the result from it, how can I do that?
Upvotes: 0
Views: 8456
Reputation: 203
Use this solution StackBlitzit is callable from any typescript file and without the need of an HTML selector. I suggest that you create a service and put this like confirm box as in this example so when you want to call it call just service method with text and color type argument that returns observable.
You can use this angular confirm box generator for testing https://costlydeveloper.github.io/ngx-awesome-popup/#/playground/confirm-box-generator
openConfirmBox() {
const newConfirmBox = new ConfirmBoxInitializer();
newConfirmBox.setTitle('Title');
newConfirmBox.setMessage('Your message!');
// Choose layout color type
newConfirmBox.setConfig({
LayoutType: DialogLayoutDisplay.SUCCESS, // SUCCESS | INFO | NONE | DANGER | WARNING
});
// Simply open the ConfirmBox
newConfirmBox.openConfirmBox$(); // subscribe to get button clicked response
}
It is my personal work I code a full dialog system similar to mat dialog but a little different, with more functionality that supports multiple dialogs, added token functionality under the hood so the developer can call dialog above dialog in chronological order, button generator with observables, and so on. Also, it gives a complete solution for confirmation boxes, toast messages, and cookie banners with the same technology.
Later I put a little more effort and put it in the open-source library, wanted to share it with the community. Support it by giving a star to the Github repo. I hope you will find it useful.
https://github.com/costlydeveloper/ngx-awesome-popup
Upvotes: 1
Reputation: 5188
Wrap it in the observable like this
confirmDialog(): Observable<boolean> {
return new Observable(observer => {
...
dialogRef.afterClosed().subscribe(dialogResult => {
observer.next(dialogResult);
observer.complete(); //to avoid memory leaks
});
});
}
or simply return afterClosed
since it is an observable, cast it to boolean.
confirmDialog(): Observable<boolean> {
...
return dialogRef.afterClosed() as Observable<boolean>;
}
Then subscribe like this
confirm() {
this.confirmService.confirmDialog().subscribe(isConfirmed => {
console.log(isConfirmed);
})
}
Upvotes: 4