Angular Material表格修改数据源后不更新的问题求助
Mat-Table编辑后未同步更新问题修复
问题描述
使用mat-table展示CompanyConnection对象列表,点击编辑按钮通过模态框更新对象后,控制台确认对象已成功更新,但表格未同步显示变更。
相关代码
table.component.html
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z4"> <!-- Columns --> <ng-container matColumnDef="DattoDomain"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Datto Domain </th> <td mat-cell *matCellDef="let company"> {{company.dattoDomain}} </td> </ng-container> <ng-container matColumnDef="connectWiseId"> <th mat-header-cell *matHeaderCellDef mat-sort-header> ConnectWise Id </th> <td mat-cell *matCellDef="let company"> {{company.connectWiseId}} </td> </ng-container> <ng-container matColumnDef="actions"> <th mat-header-cell *matHeaderCellDef>Actions</th> <td mat-cell *matCellDef="let company"> <button mat-icon-button (click)="openEditCompanyModal(company)"> <mat-icon>edit</mat-icon> </button> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
table.component.ts
export class CompanyTableComponent implements OnInit, AfterViewInit { @ViewChild(MatSort) sort: MatSort; @Input() companies: CompanyConnection[]; @Input() getError: boolean; displayedColumns: string[] = ['DattoDomain', 'connectWiseId', 'actions']; companies$: Observable<CompanyConnection[]> = of([]); dataSource = new MatTableDataSource<CompanyConnection>(); constructor( private companyDataService: CompanyDataService, private dialog: MatDialog, private changeDetectorRef: ChangeDetectorRef ) {} ngOnInit() { if (this.getError) { this.companies$ = this.companyDataService.getErrorCompanyConnections(); } else { this.companies$ = this.companyDataService.getHealthyCompanyConnections(); } this.companies$.subscribe((companies: CompanyConnection[]) => { this.dataSource.data = companies; this.changeDetectorRef.detectChanges(); }); } ngAfterViewInit() { this.dataSource.sort = this.sort; } openEditCompanyModal(company: CompanyConnection) { const dialogRef = this.dialog.open(CompanyModalComponent, { data: { company } }); dialogRef.afterClosed().subscribe((editedCompany: CompanyConnection) => { if (editedCompany) { // Update the existing company connection this.companyDataService.editCompanyConnection(editedCompany).subscribe( () => {}, error => {} ); // Retrieve the updated company connection this.companyDataService.getCompanyConnection(editedCompany.dattoDomain).subscribe( (updatedCompany: CompanyConnection | undefined) => { if (updatedCompany) { console.log('Updated company connection:', updatedCompany); } else { console.log('Company connection not found'); } }, error => { console.log('Error retrieving company connection:', error); } ); } }); } }
company-connection-service.service.ts相关方法
export class CompanyDataService { private companies: CompanyConnection[] = [ { dattoDomain: "aptdynamics", connectWiseId: "Apartment Dynamics", status: "200" }, { dattoDomain: "buckscomm", connectWiseId: "Bucks Communications", status: "200" }, { dattoDomain: "cardinalconcretecompany", connectWiseId: "Cardinal Concrete Company", status: "200" }, { dattoDomain: "centralcarolinaseeding", connectWiseId: "Central Carolina Seeding", status: "404" }, ]; private companiesSubject = new BehaviorSubject<CompanyConnection[]>(this.companies); constructor() { } getCompanyConnections(): Observable<CompanyConnection[]> { return this.companiesSubject.asObservable(); } getCompanyConnection(dattoDomain: string): Observable<CompanyConnection | undefined> { return this.getCompanyConnections().pipe( map((companies: CompanyConnection[]) => { return companies.find((company: CompanyConnection) => { return company.dattoDomain === dattoDomain; }); }) ); } getHealthyCompanyConnections(): Observable<CompanyConnection[]> { return this.getCompanyConnections().pipe( map((companies: CompanyConnection[]) => { return companies.filter((company: CompanyConnection) => { return company.status === "200"; }); }) ); } getErrorCompanyConnections(): Observable<CompanyConnection[]> { return this.getCompanyConnections().pipe( map((companies: CompanyConnection[]) => { return companies.filter((company: CompanyConnection) => { return company.status !== "200"; }); }) ); } addCompanyConnection(company: CompanyConnection): Observable<CompanyConnection[]> { this.companies.push(company); this.companiesSubject.next(this.companies); return of(this.companies); } editCompanyConnection(updatedCompany: CompanyConnection): Observable<CompanyConnection[]> { const index = this.companies.findIndex(c => c.dattoDomain === updatedCompany.dattoDomain); if (index !== -1) { this.companies[index] = updatedCompany; } return of(this.companies); } }
问题原因
- 数据更新未通知订阅者:
CompanyDataService的editCompanyConnection方法中,仅修改了私有数组companies,但未调用companiesSubject.next(this.companies)触发数据流更新,导致表格组件的订阅无法收到新数据。 - 表格数据源未同步:表格组件仅在
ngOnInit时订阅一次数据流,后续数据变更因未触发新的数据流推送,无法自动更新dataSource.data。
解决方案
1. 修复服务层的更新通知逻辑
修改CompanyDataService中的editCompanyConnection方法,更新数组后调用next方法通知所有订阅者:
editCompanyConnection(updatedCompany: CompanyConnection): Observable<CompanyConnection[]> { const index = this.companies.findIndex(c => c.dattoDomain === updatedCompany.dattoDomain); if (index !== -1) { this.companies[index] = updatedCompany; // 新增此行,触发数据流更新 this.companiesSubject.next(this.companies); } return of(this.companies); }
2. 优化表格组件的数据源绑定(可选)
可以使用Angular的async管道直接绑定数据流,简化代码并自动处理订阅与取消订阅:
- 修改
table.component.html:
<table mat-table [dataSource]="companies$ | async" matSort class="mat-elevation-z4">
- 修改
table.component.ts的ngOnInit和ngAfterViewInit:
ngOnInit() { if (this.getError) { this.companies$ = this.companyDataService.getErrorCompanyConnections(); } else { this.companies$ = this.companyDataService.getHealthyCompanyConnections(); } } ngAfterViewInit() { // 监听数据流变化,同步设置排序器 this.companies$.subscribe(data => { this.dataSource.data = data; this.dataSource.sort = this.sort; }); }
效果验证
修改后,编辑完成并调用editCompanyConnection时,服务层会推送新的数据集,表格组件的订阅会自动更新dataSource.data,表格即可同步显示最新的编辑结果。
内容的提问来源于stack exchange,提问作者Hayden Key
相关产品推荐
相关产品推荐

