Django
Django

Reputation: 55

Display Data in Angular Material Table

I'm struggling with the Angular mat-table library. I got an app with a Node.js backend and an Angular frontend. The node app provides data from a MySQL database in JSON.

Now I want to display this data in a mat-table. I have logged the data in the console, which allows me to see that the data is actually retrieved but just not displayed.

Data in Console

However, the HTML table is empty:

empty html

This is my Angular component:

component.html

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 demo-table">
  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef>ID</th>
    <td mat-cell *matCellDef="let element">{{element.id}}</td>
  </ng-container>
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>Name</th>
    <td mat-cell *matCellDef="let element">{{element.name}}</td>
  </ng-container>
  <ng-container matColumnDef="pop">
    <th mat-header-cell *matHeaderCellDef>Population</th>
    <td mat-cell *matCellDef="let element">{{element.population}}</td>
  </ng-container>


  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr
      mat-row
      (click)="clickedRows.add(row)"
      [class.demo-row-is-clicked]="clickedRows.has(row)"
      *matRowDef="let row; columns: displayedColumns;"
  ></tr>
</table>

component.ts

import {Component, OnInit,ViewChild} from '@angular/core';
import { Player } from '../player';
import { PlayerService } from '../player.service';
import { MatTableDataSource } from '@angular/material/table';
import {MatPaginator} from '@angular/material/paginator';
import {MatSort, SortDirection} from '@angular/material/sort';

/**
 * @title Binding event handlers and properties to the table rows.
 */
@Component({
  selector: 'app-players',
  styleUrls: ['players.component.css'],
  templateUrl: 'players.component.html',
})
export class PlayersComponent implements OnInit {
  displayedColumns: string[] = ['id', 'name', 'pop'];
  dataSource = new MatTableDataSource<Player>();

  @ViewChild(MatPaginator, { static: true }) paginator!: MatPaginator;
  @ViewChild(MatSort, { static: true }) sort!: MatSort;

  constructor(private playerService:PlayerService) { }

  ngOnInit(): void {
    this.getPlayers();
  }

  getPlayers() {
    this.playerService.getPlayers().subscribe(players => {
      console.log(players);
      this.dataSource.data = players;
      this.dataSource.paginator = this.paginator;
      this.dataSource.sort = this.sort;
    });
  }
  clickedRows = new Set<Player>();
}

player.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { Player } from './player';

@Injectable({
  providedIn: 'root'
})
export class PlayerService {

  constructor(private http: HttpClient) { }
  rootURL = '/api';
  getPlayers(): Observable<Player[]> {
    return this.http.get<Player[]>(this.rootURL+ '/players');
  }
}

Any ideas on this?

EDIT: Could it have something to do with how the array comes back from the API? In Node.js it is retrieved with sequelize and maybe it is the response?

// Get all Players
exports.findAll = (req, res) => {
    Player.findAll().then((players) => {
    // Send all players as response
    res.status(200).json({
      status: true,
      data: players,
    });
  });
};

Upvotes: 1

Views: 2131

Answers (2)

Yong Shun
Yong Shun

Reputation: 51125

Issue

The data returned based on the screenshot and Node.js API is not Player array, but it is an object with status and data properties.

{
  "status": 200,
  "data": [...]
}

This line expected that HTTP GET to receive Player array which is conflict with your data.

this.http.get<Player[]>(this.rootURL+ '/players');

Hence, it returns Observable with an empty array and your <mat-table> will not show the data.


Solution

Transform the data to Player array with map rxjs operator.

import { map } from 'rxjs';

getPlayers(): Observable<Player[]> {
  return this.http
    .get(this.rootURL+ '/players')
    .pipe(map((response: any) => response.data as Player[]));
}

Sample Solution on StackBlitz

Upvotes: 2

Senthil
Senthil

Reputation: 2246

Create a instance of MatTableDataSource and assign to data Source. Try this option

this.dataSource = new MatTableDataSource(players);
this.dataSource.sort = this.sort;

Ref: Using HTTP GET request to fetch data in an Angular Material Table

Upvotes: 0

Related Questions