I've seen similar questions, but nothing seems to work for me. I have a mat table where I display data from an api. But I don't know how to iterate through the 'dataSource'. Below is my code, and how I get the data when I check console log. ts file
import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
import {Pokemon, PokemonData} from '../../models/pokemon';
import {PokemonService} from '../../models/services/pokemon.service';
import {ActivatedRoute} from '@angular/router';
import {MatTableDataSource} from '@angular/material/table';
import {MatPaginator} from '@angular/material/paginator';
@Component({
selector: 'app-pokemon',
templateUrl: './pokemon.component.html',
styleUrls: ['./pokemon.component.css']
})
export class PokemonComponent implements OnInit {
public pokemon: Pokemon[];
public name: string;
public url: string;
public type: string;
expandedElement: PokemonData | null;
dataSource = new MatTableDataSource();
displayPokemonColumns: string[] = ['name', 'url', 'pokemonDetails'];
@ViewChild(MatPaginator, {read: true}) paginator: MatPaginator;
//
// // tslint:disable-next-line:typedef
// tslint:disable-next-line:typedef
// ngAfterViewInit() {
// // this.dataSource.paginator = this.paginator;
// //
// }
constructor(private pokemonService: PokemonService, private route: ActivatedRoute) {
}
// function (which is called below)issues call to API. subscribes shows to the results that are returned. adds results to shows array
onLoadPokemonList(): void {
this.pokemonService.getPokemonList().subscribe(
res => {
// this.pokemon = JSON.parse(JSON.stringify(res));
this.pokemon = res;
this.dataSource.data = this.pokemon;
setTimeout(() => {
this.dataSource.paginator = this.paginator;
});
console.log(this.dataSource);
});
}
ngOnInit(): void {
this.onLoadPokemonList();
}
}
html file
<div class="table" *ngIf="pokemon">
<h1 matColumnDef="title">POKEDEX</h1>
<table mat-table #table [dataSource]="dataSource" class="mat-elevation-z8" multiTemplateDataRows>
<!-- <table mat-table [dataSource]="pokemon.results" class="mat-elevation-z8" multiTemplateDataRows>-->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<!-- <td mat-cell *matCellDef="let res"> {{res?.name}} </td>-->
<td mat-cell *matCellDef="let res"> {{res.name}} </td>
</ng-container>
<ng-container matColumnDef="url">
<th mat-header-cell *matHeaderCellDef> URL </th>
<td mat-cell *matCellDef="let res"> {{res.url}} </td>
</ng-container>
<ng-container matColumnDef="pokemonDetails">
<th mat-header-cell *matHeaderCellDef> Pokemon Details </th>
<td mat-cell *matCellDef="let res">
<button mat-raised-button color="primary" routerLink="/pokemonData/{{res.name}}">Pokemon Details</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayPokemonColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayPokemonColumns;"
class="example-element-row"
[class.example-expanded-row]="expandedElement === row"
(click)="expandedElement = expandedElement === row ? null : row"></tr>
</table>
<mat-paginator #paginator
[pageSize]="10"
[pageSizeOptions]="[5, 10, 20]">
</mat-paginator>
</div>
this is the data I get back:
MatTableDataSource {_renderData: BehaviorSubject, _filter: BehaviorSubject, _internalPageChanges: Subject, _renderChangesSubscription: Subscriber, sortingDataAccessor: ƒ, …}filterPredicate: (data, filter) => {…}filteredData: {count: 1050, next: "https://pokeapi.co/api/v2/pokemon?offset=150&limit=150", previous: null, results: Array(150)}sortData: (data, sort) => {…}sortingDataAccessor: (data, sortHeaderId) => {…}_data: BehaviorSubject {_isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …}_filter: BehaviorSubject {_isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …}_internalPageChanges: Subject {_isScalar: false, observers: Array(0), closed: false, isStopped: false, hasError: false, …}_paginator: undefined_renderChangesSubscription: Subscriber {closed: false, _parentOrParents: null, _subscriptions: Array(1), syncErrorValue: null, syncErrorThrown: false, …}_renderData: BehaviorSubject {_isScalar: false, observers: Array(1), closed: false, isStopped: false, hasError: false, …}data: (...)filter: (...)paginator: (...)sort: (...)__proto__: DataSource
The data I need is under filteredData.
When I do
<table mat-table [dataSource]="pokemon.results" class="mat-elevation-z8" multiTemplateDataRows>
instead of dataSource, I get the correct table, but the paginator (obviously) doesn't work.
The problem is tha,t when you try to assing the paginator, the paginator is not in the DOM (you has the mat-paginator under a div that has a *ngIf). You need give a "change" to Angular to get it, so you need enclosed in a setTimeout inside subscribe function
Brief explain: your variable "pokemon" is null or undefined until you subscribe and get the data. (rememeber that you has
*ngIf="pokemon"
in html). when you get the data, the variable has value, so, "when Angular finished the instructions", refresh the app to show the table. this is the reason because you need a setTimeout