So my table works really well, except that it shows no data until either a row is clicked or the filter is used. I am unsure as to what is going on here, not sure what I am doing wrong.
I just want all data to initially load visibly into the table.
HTML:
<div fxLayoutAlign="center center">
<button mat-mini-fab color="accent" style="margin-right: 20px">
<mat-icon class="add-course-btn" (click)="stalkUser()">person_add_alt_1</mat-icon>
</button>
<mat-form-field fxFlex="40%">
<input matInput (keyup)="doFilter($event)" placeholder="Ex. Username" #input>
</mat-form-field>
</div>
<ng-container *ngIf="usersUserStalking.length > 0 && isLoading == false">
<mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="userName">
<mat-header-cell *matHeaderCellDef mat-sort-header id="nameField">Name</mat-header-cell>
<mat-cell *matCellDef="let element"><span style="cursor:pointer" (click)="navigateProfile(element.tag)"><img mat-card-avatar src="{{element.profileImage }}" class="friends-avatar-photo"> {{ element.name}}</span></mat-cell>
</ng-container>
<ng-container matColumnDef="userTag">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide.xs>Tag</mat-header-cell>
<mat-cell *matCellDef="let element" fxHide.xs>{{element.tag }}</mat-cell>
</ng-container>
<ng-container matColumnDef="userRank">
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide.xs>Rank</mat-header-cell>
<mat-cell *matCellDef="let element" fxHide.xs>{{element.rank }}</mat-cell>
</ng-container>
<ng-container matColumnDef="factionName" >
<mat-header-cell *matHeaderCellDef mat-sort-header fxHide.xs>Faction</mat-header-cell>
<mat-cell *matCellDef="let element" fxHide.xs><span style="cursor:pointer" (click)="navigateProfile(element.tag)">{{element.faction }}</span></mat-cell>
</ng-container>
<ng-container matColumnDef="stalking" >
<mat-header-cell *matHeaderCellDef>Stalking</mat-header-cell>
<mat-cell *matCellDef="let element"><button mat-stroked-button class="hover-class" color="primary"><span>Stalking</span></button></mat-cell>
</ng-container>
<!-- Row shown when there is no matching data. -->
<tr class="mat-row" *matNoDataRow>
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
</tr>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator #paginator
[pageSizeOptions]="[5, 10, 25, 100]">
</mat-paginator>
</ng-container>
<!-- Show if user is stalking no one -->
<ng-container *ngIf="usersUserStalking.length <= 0 && isLoading == false">
<div fxLayoutAlign="center center">
<h1>You are Stalking no one, use the yellow button above to stalk whoever you want!</h1>
</div>
</ng-container>
<ng-container *ngIf="isLoading">
<div class="spinner-container" fxLayoutAlign="center center">
<mat-spinner></mat-spinner>
</div>
</ng-container>
Typscript:
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Observable } from 'rxjs';
import { User } from 'src/app/auth/user.model';
import { UserService } from 'src/app/auth/user.service';
import { Router } from '@angular/router';
import { finalize } from 'rxjs/operators';
@Component({
selector: 'app-stalking',
templateUrl: './stalking.component.html',
styleUrls: ['./stalking.component.css']
})
export class FollowingComponent implements OnInit {
@Input() userUID: string;
userId: string;
displayedColumns = ["userName", "userTag", "userRank", "factionName", "stalking"];
dataSource = new MatTableDataSource<User>();
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
//User Array
userArray$: Observable<unknown[]| null>;
usersUserStalking: User[] = []
//loading
isLoading: boolean = false;
constructor(private user: UserService,
private db: AngularFirestore,
private router: Router) {}
async ngOnInit() {
await this.onReadCollection(this.userUID)
}
async onReadCollection(userUID: string){
this.isLoading = true;
this.db.collection(`users/${userUID}/stalking`).get()
.pipe(
finalize(() => {
this.isLoading = false;
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
console.log(this.usersUserStalking)
this.dataSource.data = this.usersUserStalking; // update dataScource
console.log(this.dataSource.data)
})
)
.subscribe(snaps => {
snaps.forEach(snap => {
this.user.findUserbyUID(snap.id).subscribe(user => {
this.usersUserStalking.push(<User>user)
})
})
})
}
async getFriendsForProfile(){
this.userId = this.user.getUserUID();
}
ngAfterViewInit() {
// this.dataSource.sort = this.sort;
// this.dataSource.paginator = this.paginator;
// this.dataSource.data = this.usersUserStalking
}
doFilter(event: Event | null) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
navigateProfile(userTag){
this.router.navigate(['/profile', userTag])
}
}
I have my filter set up like this:
html:
<mat-form-field fxFlex="40%">
<input matInput (keyup)="doFilter($event)" placeholder="Ex. Username" #input>
</mat-form-field>
Typescript:
doFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
I feel like I copied the angular material tables exactly like how it is done in the examples shown here: https://material.angular.io/components/table/examples
Edit 1: I updated my code and get on initial user to be visible now, but still generally have the same issue, I only see all users in the table after using the filter and clearing the filter.
Edit 2:
I fixed the issue, by doing this Jank below in ngAfterViewInit() but I would still like a better answer, than this Jank I Just made up:
ngAfterViewInit() {
setTimeout(()=> {
this.dataSource.filter = "p";
}, 100);
setTimeout(()=> {
this.dataSource.filter = "";
}, 1000);
}