Angular数据网格无法从WebAPI加载数据问题求助
Angular + Sky AG Grid 数据加载异常问题
我是Angular新手,正在实现一个从WebAPI拉取数据的基础数据网格。API返回的数据能在控制台正常打印,但把它作为rowData传入网格时完全不显示;但如果把相同数据定义成常量数组,网格却能正常渲染。
相关代码
component.ts
import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core'; import { SkyAgGridService, SkyCellType } from '@skyux/ag-grid'; import { Student } from 'src/app/models/student.model'; import { StudentsService } from 'src/app/services/students.service'; import { BehaviorSubject, Subscription } from 'rxjs'; import { ColDef, GridApi, GridOptions, GridReadyEvent, ValueFormatterParams, } from 'ag-grid-community'; import { SKY_AG_GRID_DEMO_DATA } from './basic-data-grid-docs-demo-data'; @Component({ selector: 'app-basic-data-grid-docs-demo', templateUrl: './basic-data-grid-docs-demo.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) export class SkyBasicDataGridDemoComponent implements OnInit{ students: Student[] = []; public columnDefs: ColDef[] = [ { field: 'FirstMidName', headerName: 'Name', }, { field: 'LastName', headerName: 'Last Name', }, { field: 'Gender', headerName: 'Gender' }, { field: 'EnrollmentDate', headerName: 'Enrollment date', type: SkyCellType.Date, }, ]; public gridApi: GridApi | undefined; public gridData: any[] = SKY_AG_GRID_DEMO_DATA; // 用常量数据时网格正常显示 public gridOptions: GridOptions; public searchText = ''; public getStudentsSubscription: Subscription | undefined; ngOnInit(): void { this.studentsService.getAllStudents() .subscribe({ next: (students) => { this.students= students; console.log("this is students", students); console.log(this.gridData); }, error: (response) => { console.log(response); } }); } constructor(private agGridService: SkyAgGridService, private studentsService: StudentsService) { this.gridOptions = { columnDefs: this.columnDefs, onGridReady: (gridReadyEvent): void => this.onGridReady(gridReadyEvent), rowSelection: 'single', }; this.gridOptions = this.agGridService.getGridOptions({ gridOptions: this.gridOptions, }); } public onGridReady(gridReadyEvent: GridReadyEvent): void { this.gridApi = gridReadyEvent.api; this.gridApi.sizeColumnsToFit(); } }
component.html
<div> <sky-ag-grid-wrapper> <ag-grid-angular [gridOptions]="gridOptions" [rowData]="students"> </ag-grid-angular> </sky-ag-grid-wrapper> </div>
API服务代码
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { environment } from 'src/environments/environment'; import { Student } from '../models/student.model'; @Injectable({ providedIn: 'root' }) export class StudentsService { baseApiUrl: string = environment.baseApiUrl; constructor(private http: HttpClient) { } getAllStudents(): Observable<Student[]>{ return this.http.get<Student[]>(this.baseApiUrl + 'api/student'); } }
模型定义
export interface Student{ ID: number; FirstMidName: string; LastName: string; Gender: string; EnrollmentDate: Date; }
可正常显示的常量数据
export const SKY_AG_GRID_DEMO_DATA = [ {ID:2, FirstMidName:"John333", LastName:"Doe222", Gender:"Male", EnrollmentDate:"2022-12-26T00:00:00"}, {ID:3, FirstMidName :"John2", LastName:"Doe2", Gender:"Male", EnrollmentDate:"2022-12-21T00:00:00"}, {ID:4, FirstMidName:"Lois", LastName:"Lane", Gender:"Female", EnrollmentDate:"2023-01-12T00:00:00"} ];
问题原因
组件启用了ChangeDetectionStrategy.OnPush变更检测策略,这种模式下Angular只会在输入属性引用变化、组件触发事件或手动触发变更检测时更新视图。当API返回数据后直接赋值给students数组时,虽然数组内容变了,但组件没有检测到变更,导致AG Grid没有收到数据更新。
解决方案
方案1:手动触发变更检测
在组件中注入ChangeDetectorRef,在获取到数据后手动触发变更检测:
- 导入
ChangeDetectorRef:
import { ChangeDetectorRef } from '@angular/core';
- 构造函数注入:
constructor( private agGridService: SkyAgGridService, private studentsService: StudentsService, private cdr: ChangeDetectorRef // 新增 ) { ... }
- 在subscribe的回调中触发检测:
next: (students) => { this.students = students; this.cdr.detectChanges(); // 手动触发变更检测 }
方案2:直接用AG Grid API设置行数据
通过gridApi直接设置行数据,跳过Angular变更检测的依赖:
修改ngOnInit中的subscribe回调:
next: (students) => { this.students = students; if (this.gridApi) { this.gridApi.setRowData(students); // 直接给网格设置数据 } }
方案3:用BehaviorSubject+Async管道管理数据
用BehaviorSubject存储数据,模板中用async管道订阅,这种方式能自动触发OnPush模式下的变更检测:
- 修改组件中的
students定义:
import { BehaviorSubject } from 'rxjs'; // 替换原来的students数组 students$ = new BehaviorSubject<Student[]>([]);
- 更新subscribe回调:
next: (students) => { this.students$.next(students); // 发送新数据到Subject }
- 修改模板中的rowData绑定:
<ag-grid-angular [gridOptions]="gridOptions" [rowData]="students$ | async">
内容的提问来源于stack exchange,提问作者Shivansh Trigunait
相关产品推荐
相关产品推荐

