Angular Material 16对话框在API请求完成前关闭问题排查与解决
问题原因
按钮上同时绑定了[mat-dialog-close]="true"和(click)="deleteRecords()",Angular事件处理的优先级中,mat-dialog-close指令的关闭逻辑会先于组件的click事件执行。这就导致对话框在deleteRecords()里的forkJoin请求还未处理完成时就已关闭,afterClosed()回调被提前触发,里面的#setFirstTablePage()和resetCheckboxes()先执行,而对话框内的API请求才刚刚发起。
解决方案
移除按钮上的[mat-dialog-close]="true",完全通过deleteRecords()方法里的dialogRef.close()控制对话框关闭时机,确保只有当forkJoin的所有API请求完成后,才关闭对话框并触发afterClosed()回调。
修改后的代码示例
按钮代码
<button mat-raised-button cdkFocusInitial (click)="deleteRecords()" color="accent">DELETE RECORDS</button>
对话框组件代码(仅调整close传参,逻辑不变)
@Component({ selector: 'delete-records-dialog', templateUrl: 'delete-records-dialog.html', }) export class DeleteRecordsDialog { recordsToDelete: Array<object>; constructor( @Inject(MAT_DIALOG_DATA) public data: { recordsToDelete: Array<object>, }, private apiService: ApiService, private dialogRef: MatDialogRef<DeleteRecordsDialog>, ) { this.recordsToDelete = data.recordsToDelete; } deleteRecords() { const httpReuests = this.recordsToDelete.map((id) => ( this.apiService.deleteRecord(id) )); const complete = () => { this.dialogRef.close(true); // 传入true,和原mat-dialog-close的返回值保持一致 } forkJoin(httpReuests).subscribe({ complete }); } }
打开对话框代码(无需修改)
openConfirmDialog() { const { recordsToDelete } = this; const dialogRef = this.dialog.open(DeleteRecordsDialog, { data: { recordsToDelete } }); dialogRef.afterClosed().subscribe((isSubmit) => { if (isSubmit) { this.#setFirstTablePage(); this.resetCheckboxes(); } }); }
修改后,点击按钮会先执行deleteRecords(),等待forkJoin所有请求完成后,才会调用dialogRef.close(true)关闭对话框,此时afterClosed()回调才会触发,里面的操作也会在API请求完成后执行。
内容的提问来源于stack exchange,提问作者dman
相关产品推荐
相关产品推荐

