共享服务中MatTableDataSource取数后组件内dataSource未定义,无法渲染mat-table
问题排查与解决方案
1. 异步请求未正确处理导致数据源未初始化
API请求是异步操作,若服务中直接返回未等待数据的MatTableDataSource,组件拿到的会是未填充数据的空对象甚至undefined。
修正后的服务代码
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { MatTableDataSource } from '@angular/material/table'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class SharedService { constructor(private http: HttpClient) {} // 返回Observable,等待API数据返回后再创建数据源 getTableData<T>(apiUrl: string): Observable<MatTableDataSource<T>> { return this.http.get<T[]>(apiUrl).pipe( map(resData => new MatTableDataSource(resData)) ); } }
组件中正确订阅赋值
import { Component, OnInit } from '@angular/core'; import { SharedService } from './shared.service'; import { MatTableDataSource } from '@angular/material/table'; import { YourDataType } from './your-data-type'; @Component({ selector: 'app-target-component', templateUrl: './target-component.component.html' }) export class TargetComponent implements OnInit { dataSource!: MatTableDataSource<YourDataType>; displayedColumns: string[] = ['id', 'name', 'value']; // 替换为你的列名 constructor(private sharedService: SharedService) {} ngOnInit(): void { this.sharedService.getTableData<YourDataType>('http://localhost:3000/your-api-endpoint') .subscribe(dataSource => { this.dataSource = dataSource; }); } }
2. 避免同步返回未填充数据的数据源
不要在服务中先创建空的MatTableDataSource再异步赋值,这种写法会导致组件拿到数据源时,内部data属性还未被填充:
// 错误写法,禁止使用 getTableData() { const dataSource = new MatTableDataSource(); this.http.get('url').subscribe(data => { dataSource.data = data; }); return dataSource; // 此时dataSource.data仍为空 }
3. 使用Async管道简化异步处理
如果不想手动管理订阅,可以用Angular的async管道自动处理异步流:
组件代码
dataSource$!: Observable<MatTableDataSource<YourDataType>>; ngOnInit(): void { this.dataSource$ = this.sharedService.getTableData<YourDataType>('http://localhost:3000/your-api-endpoint'); }
模板代码
<table mat-table [dataSource]="dataSource$ | async" class="mat-elevation-z8"> <!-- 列定义示例 --> <ng-container matColumnDef="id"> <th mat-header-cell *matHeaderCellDef> ID </th> <td mat-cell *matCellDef="let item"> {{item.id}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table>
4. 检查JSON Server返回格式
确保JSON Server的API返回纯数组格式数据。若返回的是嵌套对象(如{ list: [...] }),需要在服务中提取数组部分:
getTableData<T>(apiUrl: string): Observable<MatTableDataSource<T>> { return this.http.get<{ list: T[] }>(apiUrl).pipe( map(res => new MatTableDataSource(res.list)) ); }
内容的提问来源于stack exchange,提问作者Sameh M Darwish
相关产品推荐
相关产品推荐

