重新加载分页的mat-table无法在Angular中显示行
我有一个mat-table从firebase加载数据.
全matches.component.html ... <mat-table #table [dataSource]="dataSource" class="mat-elevation-z8"> ... <ng-container matColumnDef="rank"> <mat-header-cell *matHeaderCellDef> Rank </mat-header-cell> <mat-cell *matCellDef="let entry"> {{entry.rank}} </mat-cell> </ng-container> <ng-container matColumnDef="weightClass"> <mat-header-cell *matHeaderCellDef> Weight Class </mat-header-cell> <mat-cell *matCellDef="let entry"> {{entry.weightClass}} </mat-cell> </ng-container> ... <mat-header-row *matHeaderRowDef="columnsToDisplay"></mat-header-row> <mat-row *matRowDef="let row; columns: columnsToDisplay;"></mat-row> </mat-table> ... 根据在线建议(我还不完全了解),我选择使用dataSource对象来填充我的表. dataSource在all-matches.component.ts中实例化: 全matches.component.ts ... @Component({ selector: 'app-all-matches',templateUrl: './all-matches.component.html',styleUrls: ['./all-matches.component.scss'] }) export class AllMatchesComponent implements OnInit,OnDestroy,AfterViewInit { private columnsToDisplay = ['rank','weightClass','ageClass','athlete1Name','athlete2Name','gender','tournamentName','location','date','matchRating','videoUrl']; //TODO make this dynamic somehow private loading = true; ... @ViewChild(MatPaginator) paginator: MatPaginator; constructor(private authService: AuthorizationService,private d3Service: D3Service,private dbService: DatabaseService,private textTransformationService: TextTransformationService,private dataSource: MatchDataSource) { } ngOnInit() { ... this.pageSize = 2; //TODO increase me to something reasonable this.dataSource = new MatchDataSource(this.dbService); this.dataSource.loadMatches('test','',this.pageSize); this.dbService.getMatchCount().subscribe(results=>{ this.matchCount = results; }); ... } MatchDataSource.model.ts import {CollectionViewer,DataSource} from "@angular/cdk/collections"; import { BehaviorSubject,Observable,of } from 'rxjs'; import { catchError,finalize } from 'rxjs/operators'; import { Match } from './match.model'; import { DatabaseService } from './database.service'; import { Injectable } from '@angular/core'; @Injectable() export class MatchDataSource implements DataSource<Match> { private matchesSubject = new BehaviorSubject<Match[]>([]); private loadingMatches = new BehaviorSubject<boolean>(false); public loading$= this.loadingMatches.asObservable(); constructor(private dbService: DatabaseService) {} connect(collectionViewer: CollectionViewer): Observable<Match[]> { return this.matchesSubject.asObservable(); } disconnect(collectionViewer: CollectionViewer): void { this.matchesSubject.complete(); this.loadingMatches.complete(); } loadMatches(matchId: string,filter = '',sortDirection='asc',pageIndex: number,pageSize: number) { this.loadingMatches.next(true); this.dbService.getKeyOfMatchToStartWith(pageIndex,pageSize).subscribe(keyIndex=>{ this.dbService.getMatchesFilteredPaginator(keyIndex,pageSize).pipe( catchError(()=> of([])),finalize(()=>{ //TODO the tutorial here https://blog.angular-university.io/angular-material-data-table/ toggled the loading spinner off here,but it seemed to work better below for me? }) ) .subscribe(matches => { let results = this.makeIntoArray(matches); this.matchesSubject.next(results); // console.log("loading done"); this.loadingMatches.next(false); }); }); } makeIntoArray(matches: any){ let results = []; //TODO there should be a way to tighten the below up for(var i in matches){ let obj1 = {id:matches[i].id}; if(matches[i].matchDeets){ let obj2 = matches[i].matchDeets; obj1 = Object.assign({},obj1,obj2); } results.push(obj1); } // console.log(results); return results; } } 行加载得很好(虽然我对缩放有一些担心,因为我用可观察量计算总行数(为什么没有直接的方法来计算firebase节点中的条目?)). 但是,当我重新加载页面时,旋转器永远不会被解散,并且行永远不会填充.我欢迎任何建议! 再现我的问题: git clone https://github.com/Atticus29/dataJitsu.git cd dataJitsu git checkout matTableSO 在/ src / app中创建一个api-keys.ts文件,并用随后的文本填充它 API-keys.ts export var masterFirebaseConfig = { apiKey: "AIzaSyCaYbzcG2lcWg9InMZdb10pL_3d1LBqE1A",authDomain: "dataJitsu.firebaseapp.com",databaseURL: "https://datajitsu.firebaseio.com",storageBucket: "",messagingSenderId: "495992924984" }; export var masterStripeConfig = { publicApiTestKey: "pk_test_NKyjLSwnMosdX0mIgQaRRHbS",secretApiTestKey: "sk_test_6YWZDNhzfMq3UWZwdvcaOwSa",publicApiKey: "",secretApiKey: "" }; 然后,返回终端会话,键入: npm install ng serve 解决方法
创建BehaviorSubject对象&然后将其转换为Observable是一种好方法,但更改发生在与AllMatchesComponent不同的上下文中.因此,您不仅要订阅组件类中$loading的更改,还要更新模型值(更改检测)
你可以用以下方式做到这一点: 1.使用NgZone.run():NgZone是一个可注入的服务,用于执行Angular区域内部或外部的工作.通过run运行函数将允许您从上下文执行的任务重新进入Angular区域. import { NgZone } from '@angular/core'; constructor(...,private nz: NgZone) { } 然后,在AllMatchesComponent中更新数据源对象创建: this.dataSource = new MatchDataSource(this.dbService,this.nz); 并为此更新服务代码: loadMatches(matchId: string,finalize(()=>{ //TODO }) ) .subscribe(matches => { let results = this.makeIntoArray(matches); this.nz.run(() => { this.matchesSubject.next(results); this.loadingMatches.next(false); }); }); }); } 这里我只更新了你的代码,在订阅中,我用NgZone.run()调用了.next()调用.无需其他更改&异步管道应该按预期工作 你可以参考Github Repo example.检查AllMatchesComponent& MatchDataSource 2.在另一种方法中,您可以跳过使用异步管道和放大器.只需订阅datasource.$loading然后使用ChangeDetectorRef更新模型var中的更改. import { ChangeDetectorRef } from '@angular/core'; constructor(...,private cdr: ChangeDetectorRef ) { } ngOnInit() { //Keep other code as it is // Uncomment loading$subscribe & update it as below this.dataSource.loading$.subscribe(result =>{ this.showLoader = result; this.cdr.detectChanges(); }); } 不对MatchDataSource服务进行任何更改.将加载器模板代码更新为: <div class="spinner-container" *ngIf="showLoader"> <mat-spinner id="spinner"></mat-spinner> </div> 然后这将按预期工作&更改将更新. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |