You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
  }
}

问题原因

  1. 数据更新未通知订阅者:CompanyDataService的editCompanyConnection方法中,仅修改了私有数组companies,但未调用companiesSubject.next(this.companies)触发数据流更新,导致表格组件的订阅无法收到新数据。
  2. 表格数据源未同步:表格组件仅在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 02:48:09