Angular 6中MatDialog关闭并更新数据库后如何刷新组件?
我明白你现在遇到的困扰:在对话框里完成客户(或车辆、司机、预约)的添加/编辑操作后,展示数据的组件没法立刻更新显示最新内容,只有切换路由再返回才会生效。这是因为当前的实现里,对话框组件完成操作后没有通知父展示组件去重新获取数据,咱们来一步步解决这个问题。
问题根源分析
你现在在AddClientComponent的saveClient方法里调用了this.ngOnInit(),但这个方法里的router.navigate(['/admin/clients'])其实不会让ClientsComponent重新执行ngOnInit(因为已经处于该路由下了)。而且对话框是独立的模态组件,它关闭后,父组件ClientsComponent完全不知道数据已经发生了变化,自然不会主动去拉取最新的客户列表。
解决方案一:利用Dialog的afterClosed()监听刷新(推荐简单场景)
最直接有效的方式是借助Angular Material Dialog的afterClosed() Observable,在父展示组件里监听对话框的关闭事件,一旦确认完成了增改操作,就主动调用数据获取方法刷新列表。
1. 优化AddClientComponent,移除不必要的路由导航
对话框是模态弹窗,不需要在组件内部做路由跳转,关闭时传递一个标记告诉父组件是否需要刷新数据:
export class AddClientComponent implements OnInit { clientForm: FormGroup; constructor( private fb: FormBuilder, private clientService: ClientService, private toastr: ToastrService, public dialogRef: MatDialogRef<AddClientComponent> ) { this.clientForm = this.fb.group({ 'clientname': new FormControl(""), 'clientphoneno': new FormControl(""), 'clientemail': new FormControl(""), 'clientaddress': new FormControl("") }); } ngOnInit() { // 移除这里的router.navigate,弹窗不需要导航 } saveClient(formdata: any) { let theForm = this.clientForm.value; this.clientService.addClient(theForm).subscribe(data => { if (data.success === false) { this.toastr.error(data.message); } else { this.toastr.success(data.message); // 关闭弹窗时传递true,标记数据已更新 this.dialogRef.close(true); } this.clientForm.reset(); }); } close() { this.dialogRef.close(false); // 取消操作时传递false } }
2. 修改ClientsComponent,监听弹窗关闭并刷新数据
在打开添加/编辑弹窗后,订阅afterClosed()事件,根据返回值判断是否需要刷新列表:
export class ClientsComponent implements OnInit { public currentClient: IClient; clients: any; constructor( public dialog: MatDialog, private dialogService: DialogService, private clientService: ClientService, private router: Router ) {} openAddClientDialog() { const dialogRef = this.dialogService.open(AddClientComponent, { width: '500px' }); // 监听弹窗关闭事件 dialogRef.afterClosed().subscribe(result => { // 如果返回true,说明数据已更新,刷新列表 if (result) { this.getAllClients(); } }); } openEditClientDialog(id) { const dialogRef = this.dialogService.open(EditClientComponent, { width: '500px', data: { 'id': id } }); // 同样监听编辑弹窗的关闭事件 dialogRef.afterClosed().subscribe(result => { if (result) { this.getAllClients(); } }); } ngOnInit() { this.getAllClients(); } getAllClients() { this.clientService.getClients().subscribe((res) => { this.clients = res; }, err => { console.log(err); }); } deleteClient(id) { this.clientService.deleteClient(id) .subscribe(res => { // 删除后直接刷新列表,无需路由跳转 this.getAllClients(); }, (err) => { console.log(err); }); } }
3. 同步修改EditClientComponent
和添加组件逻辑一致,编辑完成后关闭弹窗时传递true,通知父组件刷新:
// EditClientComponent的save方法示例 saveClient(formdata: any) { const clientId = this.data.id; // 从弹窗传入的data中获取客户ID this.clientService.editClient(clientId, formdata).subscribe(data => { if (data.success === false) { this.toastr.error(data.message); } else { this.toastr.success(data.message); this.dialogRef.close(true); } this.clientForm.reset(); }); }
解决方案二:用BehaviorSubject共享数据(适合复杂多组件场景)
如果你的应用中有多个组件需要共享客户数据,可以在ClientService里用BehaviorSubject存储数据,增改操作后直接更新Subject,所有订阅的组件都会自动刷新,无需手动调用获取方法:
1. 改造ClientService
import { BehaviorSubject } from 'rxjs'; import { tap } from 'rxjs/operators'; // ...其他依赖注入 @Injectable() export class ClientService { // 用BehaviorSubject存储客户列表,初始值为空数组 private clientsSubject = new BehaviorSubject<any[]>([]); // 暴露Observable供组件订阅 public clients$ = this.clientsSubject.asObservable(); // ...其他方法 getClients() { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this._http.get('http://localhost:3000/admin/clients', options).pipe( map((response: Response) => response.json()), // 获取到数据后更新Subject tap(clients => this.clientsSubject.next(clients)) ); } addClient(oClient) { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this._http.post('http://localhost:3000/admin/clients/add', JSON.stringify(oClient), options).pipe( map((response: Response) => response.json()), // 添加成功后重新获取列表并更新Subject tap(() => this.getClients().subscribe()) ); } editClient(clientId, oClient) { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this._http.put(`http://localhost:3000/admin/clients/edit/${clientId}`, JSON.stringify(oClient), options).pipe( map((response: Response) => response.json()), // 编辑成功后重新获取列表并更新Subject tap(() => this.getClients().subscribe()) ); } }
2. 修改ClientsComponent订阅数据
export class ClientsComponent implements OnInit { public currentClient: IClient; clients: any; constructor( public dialog: MatDialog, private dialogService: DialogService, private clientService: ClientService, private router: Router ) {} ngOnInit() { // 订阅clients$,数据变化时自动更新组件的clients变量 this.clientService.clients$.subscribe(clients => { this.clients = clients; }); // 首次加载数据 this.clientService.getClients().subscribe(); } // ...其他方法(openAddClientDialog、openEditClientDialog等可以保持不变,不需要手动调用getAllClients) }
方案选择
- 如果你只是简单的单组件展示数据,方案一足够直接有效,代码改动小。
- 如果你的应用有多个组件需要同步客户数据,方案二更适合,能减少重复的HTTP请求,实现数据的统一管理。
内容的提问来源于stack exchange,提问作者sneha_h

