I have been following the Angular Material Data Table paginator tutorial here.
When they construct their paginator, they declare a paginator using
@ViewChild(MatPaginator) paginator: MatPaginator;
in their component.ts file. With this declaration, they are able to access properties later in the same file:
ngAfterViewInit() {
this.paginator.page
.pipe(
tap(() => this.loadLessonsPage())
)
.subscribe();
}
without issue.
When I do the same thing in my component:
export class AllMatchesComponent implements OnInit, OnDestroy, AfterViewInit {
...
@ViewChild(MatPaginator) paginator: MatPaginator;
...
ngAfterViewInit(){
console.log(this.paginator);
this.paginator.page
.pipe(
tap(()=> this.loadMatchesPage())
)
.subscribe();
}
...
, I get the following error in the console:
ERROR TypeError: Cannot read property 'page' of undefined at AllMatchesComponent.ngAfterViewInit (all-matches.component.ts:50)
When I try to take a look at their example repo (going to branch 2-data-table-finished), the code includes all of the filtering and sorting syntax, which I haven't gotten to in the tutorial yet. In other words, their example code does not resemble the step I'm on in the tutorial, and there are no other branches that capture the code in the simpler state.
I'm at a loss for figuring out why paginator is undefined. Any ideas?
My personal repo can be found here:
git clone https://github.com/Atticus29/dataJitsu.git
cd dataJitsu
git checkout SO-paginator-freeze
For convenience, here's the entire all-matches.component.ts:
import { Component, OnInit, OnDestroy, AfterViewInit, ViewChild } from '@angular/core';
import { D3Service } from '../d3.service';
import { DatabaseService } from '../database.service';
import { TextTransformationService } from '../text-transformation.service';
import * as firebase from 'firebase/app';
import { MatTableDataSource, MatSort } from '@angular/material';
import { MatPaginatorModule } from '@angular/material/paginator';
import { DataSource } from '@angular/cdk/table';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import { MatchDataSource } from '../matchDataSource.model';
import { AuthorizationService } from '../authorization.service';
import { Subject } from 'rxjs/Subject';
import { tap } from 'rxjs/operators';
import { MatPaginator } from '@angular/material';
@Component({
selector: 'app-all-matches',
templateUrl: './all-matches.component.html',
styleUrls: ['./all-matches.component.scss']
})
export class AllMatchesComponent implements OnInit, OnDestroy, AfterViewInit {
private dataSource: MatchDataSource;
private columnsToDisplay = ['rank','weightClass', 'ageClass','athlete1Name', 'athlete2Name', 'gender','tournamentName','location', 'date', 'matchRating', 'videoUrl']; //TODO make this dynamic somehow
private loading = true;
user: any = null;
private ngUnsubscribe: Subject<void> = new Subject<void>();
private matchCount: number;
private pageSize: number;
@ViewChild(MatPaginator) paginator: MatPaginator;
constructor(private authService: AuthorizationService, private d3Service: D3Service, private dbService: DatabaseService, private textTransformationService: TextTransformationService) { }
ngOnInit() {
this.authService.getCurrentUser().takeUntil(this.ngUnsubscribe).subscribe(user=>{
this.user = user;
},err=>{
console.log(err);
});
this.pageSize = 2;
this.dataSource = new MatchDataSource(this.dbService);
this.dataSource.loadMatches('test', '', '', 0, this.pageSize);
this.dbService.getMatchCount().subscribe(results=>{
this.matchCount = results;
});
}
ngAfterViewInit(){
console.log(this.paginator);
this.paginator.page
.pipe(
tap(()=> this.loadMatchesPage())
)
.subscribe();
}
loadMatchesPage(){
this.dataSource.loadMatches('TODO', '', 'asc', this.paginator.pageIndex, this.paginator.pageSize);
}
ngOnDestroy(){
console.log("onDestroy is called");
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
}
And here's the corresponding html:
<script type='text/javascript' src='http://d3js.org/d3.v3.min.js'></script>
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase.js'></script>
<script type='text/javascript' src='d3fire.min.js'></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.1.3"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.geom.js?2.1.3"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?2.1.3"></script>
<br>
<div class="" *ngIf='user'>
<div class="spinner-container" *ngIf="loading$">
<mat-spinner id="spinner"></mat-spinner>
</div>
<mat-table #table [dataSource]="dataSource" class="mat-elevation-z8" *ngIf="!loading$">
<!-- TODO add paidStatus to ngIf -->
<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>
<ng-container matColumnDef="ageClass">
<mat-header-cell *matHeaderCellDef> Age Class </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.ageClass}} </mat-cell>
</ng-container>
<ng-container matColumnDef="athlete1Name">
<mat-header-cell *matHeaderCellDef> Athlete 1 </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.athlete1Name}} </mat-cell>
</ng-container>
<ng-container matColumnDef="athlete2Name">
<mat-header-cell *matHeaderCellDef> Athlete 2 </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.athlete2Name}} </mat-cell>
</ng-container>
<ng-container matColumnDef="gender">
<mat-header-cell *matHeaderCellDef> Gender </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.gender}} </mat-cell>
</ng-container>
<ng-container matColumnDef="location">
<mat-header-cell *matHeaderCellDef> Location </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.location}} </mat-cell>
</ng-container>
<ng-container matColumnDef="tournamentName">
<mat-header-cell *matHeaderCellDef> Tournament </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.tournamentName}} </mat-cell>
</ng-container>
<ng-container matColumnDef="date">
<mat-header-cell *matHeaderCellDef> Date </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.date | date:'shortDate'}} </mat-cell>
</ng-container>
<ng-container matColumnDef="videoUrl">
<mat-header-cell *matHeaderCellDef> Video </mat-header-cell>
<mat-cell *matCellDef="let entry"> <a href='{{entry.videoUrl}}'>Click</a> </mat-cell>
<!-- <i class="material-icons right">video</i> -->
</ng-container>
<ng-container matColumnDef="matchRating">
<mat-header-cell *matHeaderCellDef> Match Rating </mat-header-cell>
<mat-cell *matCellDef="let entry"> {{entry.matchRating}}</mat-cell>
<!-- <i class="material-icons right">video</i> -->
</ng-container>
<mat-header-row *matHeaderRowDef="columnsToDisplay"></mat-header-row>
<mat-row *matRowDef="let row; columns: columnsToDisplay;"></mat-row>
</mat-table>
<mat-paginator [length]='matchCount' [pageSize]="2" [pageSizeOptions]="[2, 5, 10]"></mat-paginator>
</div>