重新加载分页的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区域.
因此,在组件和组件中注入ngzone. MatchDataSource:

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>

然后这将按预期工作&更改将更新.

相关文章

ANGULAR.JS:NG-SELECTANDNG-OPTIONSPS:其实看英文文档比看中...
AngularJS中使用Chart.js制折线图与饼图实例  Chart.js 是...
IE浏览器兼容性后续前言 继续尝试解决IE浏览器兼容性问题,...
Angular实现下拉菜单多选写这篇文章时,引用文章地址如下:h...
在AngularJS应用中集成科大讯飞语音输入功能前言 根据项目...
Angular数据更新不及时问题探讨前言 在修复控制角标正确变...