Friday 29 April 2022

Angular Material table filtering out all results when input is initially blank, will work after typing into input Only

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="" class="friends-avatar-photo"> </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></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></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)"></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 ""</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.



from Angular Material table filtering out all results when input is initially blank, will work after typing into input Only

No comments:

Post a Comment