Search code examples
angulardata-bindingangular-material

table datasource updating but not displaying the content


i'm trying to build a movie watchlist table for a project. The problem is that, when i get my array of data from firebase, i create a MatTableDataSource and attribute it the array i received, but i don't get any output on screen. How do i fix this ? Do i need to call a reload function ?

Example of what the page shows : https://i.sstatic.net/SMgRp.jpg

main-page-component.ts

import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { Movie } from 'src/app/core/models/movie';
import { MovieService } from 'src/app/core/services/movie.service';

@Component({
  selector: 'app-main-page',
  templateUrl: './main-page.component.html',
  styleUrls: ['./main-page.component.scss']
})


export class MainPageComponent implements OnInit {
  
  movieData: MatTableDataSource<Movie>;
  displayedColumns: string[] = ['title', 'genre', 'watchStatus', 'rating', 'wouldRecommend'];
  constructor(private movieService: MovieService) { }

  async getMoviesOfUser() {
    let resultData : Movie[] = this.movieService.getAllMoviesOfUser("1W43qABYx3WAdcrpL2cz");
    this.movieData = new MatTableDataSource(resultData);
  }

  ngOnInit(): void {
    this.getMoviesOfUser();
    console.log(this.movieData.data);
  }

}

main-page-component.html

<div class="container-page">
    <p id="toolbar-top">
        <mat-toolbar color="primary">
            Welcome (de pus numele userului aici)
            <button mat-icon-button id="logout-icon">
                <mat-icon>logout</mat-icon> Logout
            </button>
        </mat-toolbar>
    </p>
    <table class="mat-elevation-z8 table-main" mat-table [dataSource]="movieData" >
        <ng-container matColumnDef="title">
            <th mat-header-cell *matHeaderCellDef> Title </th>
            <td mat-cell *matCellDef="let element"> {{element.title}} </td>
        </ng-container>
        <ng-container matColumnDef="genre">
            <th mat-header-cell *matHeaderCellDef> Genre </th>
            <td mat-cell *matCellDef="let element"> {{element.genre}} </td>
        </ng-container>
        <ng-container matColumnDef="watchStatus">
            <th mat-header-cell *matHeaderCellDef> Status </th>
            <td mat-cell *matCellDef="let element"> {{element.watchStatus}} </td>
        </ng-container>
        <ng-container matColumnDef="rating">
            <th mat-header-cell *matHeaderCellDef> Rating </th>
            <td mat-cell *matCellDef="let element"> {{element.rating}} </td>
        </ng-container>
        <ng-container matColumnDef="wouldRecommend">
            <th mat-header-cell *matHeaderCellDef> Recommended ? </th>
            <td mat-cell *matCellDef="let element"> {{element.wouldRecommend}} </td>
        </ng-container>

        <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    </table>
</div>

movie-service.ts

import { Injectable } from '@angular/core';

import { AngularFirestore } from '@angular/fire/compat/firestore';
import { Movie } from '../models/movie';


@Injectable({
  providedIn: 'root'
})
export class MovieService {
  moviesRef = this.database.collection('Movies');

  constructor(private database: AngularFirestore) { }

  getAllMoviesOfUser(userID: string) {
    let result: any[] = [];
    this.moviesRef.ref.where('includedBy', '==', userID).get().then((querySnapshot) => {
      querySnapshot.forEach((doc) => result.push(doc.data()));
    });
    return result;
  }
}

movie interface

export interface Movie {
    includedBy : string;
    title : string;
    genre : string;
    watchStatus : string;
    rating : string;
    wouldRecommend : string;
}

Solution

  • First of all I would recomend you to add return types to a methods. It will help you.

    second. in component you have async, but where is await?

    third. in service you have asyncroneous request to db. but you return result before the request is fullfilled. so you have empty array.

    problem not in mat-table. problem in obtaining data from service.

    try this

    async getMoviesOfUser() {
        let resultData : Movie[] = await this.movieService.getAllMoviesOfUser("1W43qABYx3WAdcrpL2cz");
        this.movieData = new MatTableDataSource(resultData);
    }
    

    and in service something like this

     async getAllMoviesOfUser(userID: string) {
        const snapShots = await this.moviesRef.ref.where('includedBy', '==', userID).get();
        return snapShots.map(item => item.data());
     }