Mat-table不显示数据

huangapple go评论65阅读模式
英文:

Mat-table doesn't show data

问题

It seems like your mat-table isn't displaying data after an API call. However, it works when you manually inject data. You also noticed a difference in the logs for the two scenarios.

Based on the provided information, it appears that your issue might be related to the timing of your API call. When you directly inject data, it's available immediately, but with the API call, there might be a delay in fetching the data.

To resolve this, you can try the following steps:

  1. Ensure that the API call is successfully fetching the data by adding console logs in your component to see the response from the API.

  2. Make sure you're updating the MatTableDataSource after the API call completes. You can do this inside a .subscribe() block to ensure the data is available before updating the data source.

Here's an example of how to do it:

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

updateDrinksFromAPI(): void {
    this.drinksService.getDrinks().subscribe(data => {
        // Assuming data is an array of drinks from your API
        this.alcohols = data.filter(drink => drink.alcohol);
        this.nonAlcohols = data.filter(drink => !drink.alcohol);
        
        this.dataSourceAlcohol = new MatTableDataSource(this.alcohols);
        this.dataSourceNonAlcohol = new MatTableDataSource(this.nonAlcohols);
    });
}

Ensure that this.updateDrinksFromAPI() is called in ngOnInit() to trigger the API call when the component initializes.

By following these steps, you should be able to populate your mat-table with data from the API correctly.

英文:

My mat-table does not show any data after an API call. It does show data when I directly inject the data, even though to me, it seems exactly the same. I can't seem to find why this goes wrong.

prijslijst.component.html

<div id="prijslijst_bier">
<table mat-table [dataSource]="dataSourceAlcohol" class="mat-table">

    <!--- Note that these columns can be defined in any order.
          The actual rendered columns are set as a property on the row definition" -->
  
    <!--  Naam Column -->
     <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> Name </th>
        <td mat-cell *matCellDef="let alcohol" class="mat-cell"> {{alcohol.name}} </td>
    </ng-container>  
  
    <!-- Begin prijs Column -->
    <ng-container matColumnDef="startPrice">
      <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> Beginprijs </th>
      <td mat-cell *matCellDef="let alcohol" class="mat-cell"> {{alcohol.startPrice}} </td>
    </ng-container>

    <!-- Actuele prijs Column -->
    <ng-container matColumnDef="currentPrice">
      <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> Actuele prijs </th>
      <td mat-cell *matCellDef="let alcohol" class="mat-cell"> {{alcohol.currentPrice}} </td>
    </ng-container>

    <!-- Aantal verkocht Column -->
    <ng-container matColumnDef="numberSold">
      <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> # </th>
      <td mat-cell *matCellDef="let alcohol" class="mat-cell"> {{alcohol.numberSold}} </td>
    </ng-container>
  
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="addOrder(row)"></tr>
</table>  
</div>

<div id="prijslijst_fris">
  <table mat-table [dataSource]="dataSourceNonAlcohol" class="mat-table">
  
      <!--- Note that these columns can be defined in any order.
            The actual rendered columns are set as a property on the row definition" -->
    
      <!--  Naam Column -->
       <ng-container matColumnDef="name">
          <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> Name </th>
          <td mat-cell *matCellDef="let nonAlcohol" class="mat-cell"> {{nonAlcohol.name}} </td>
      </ng-container>  
    
      <!-- Begin prijs Column -->
      <ng-container matColumnDef="startPrice">
        <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> Start Price </th>
        <td mat-cell *matCellDef="let nonAlcohol" class="mat-cell"> {{nonAlcohol.startPrice}} </td>
      </ng-container>
  
      <!-- Actuele prijs Column -->
      <ng-container matColumnDef="currentPrice">
        <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> Current Price </th>
        <td mat-cell *matCellDef="let nonAlcohol" class="mat-cell"> {{nonAlcohol.currentPrice}} </td>
      </ng-container>
  
      <!-- Aantal verkocht Column -->
      <ng-container matColumnDef="numberSold">
        <th mat-header-cell *matHeaderCellDef class="mat-header-cell"> # </th>
        <td mat-cell *matCellDef="let nonAlcohol" class="mat-cell"> {{nonAlcohol.numberSold}} </td>
      </ng-container>
    
      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="addOrder(row)"></tr>
  </table>  
  </div>

prijslijst.component.ts

typescript
import { Component } from '@angular/core';
import {MatTableDataSource, MatTableDataSourcePaginator} from '@angular/material/table';
import { DrinksService } from '../drinks/drinks.service';
import { Drink } from '../drinks/drink';
@Component({
selector: 'app-prijslijst',
templateUrl: './prijslijst.component.html',
styleUrls: ['./prijslijst.component.css']
})
export class PrijslijstComponent {
private alcohols: Drink[] = [];
private nonAlcohols: Drink[] = [];
dataSourceAlcohol!: MatTableDataSource<Drink, MatTableDataSourcePaginator>;
dataSourceNonAlcohol!: MatTableDataSource<Drink, MatTableDataSourcePaginator>;
displayedColumns: string[] = ['name', 'startPrice', 'currentPrice', 'numberSold'];
constructor(private drinksService: DrinksService) { 
}
ngOnInit(): void {
this.updateDrinks();
this.dataSourceAlcohol = new MatTableDataSource(this.alcohols);
this.dataSourceNonAlcohol = new MatTableDataSource(this.nonAlcohols);
}
addOrder(drink: Drink) {
drink.numberInOrder = drink.numberInOrder + 1;
}
updateDrinks(): void {
this.alcohols = this.drinksService.getAlcoholDrinks();
this.nonAlcohols = this.drinksService.getNonAlcoholDrinks();
}
}

drink.service.ts

typescript
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { Drink } from './drink';
@Injectable({
providedIn: 'root'
})
export class DrinksService {
constructor(private http:HttpClient) { }
private url: string = 'http://localhost:3000/drinks';
drinks: Drink[] = [];
setupDrinks(): void {
this.getDrinks().subscribe(drinks => {
drinks.forEach(drink => this.drinks.push(drink))
});
}
getDrinks(): Observable<Drink[]> {
console.log('getDrinks')
return this.http.get<Drink[]>(this.url);
}
getAlcoholDrinks(): Drink[] {
let alcoholDrinks: Drink[] = [];
this.getDrinks().subscribe(drinks => {
drinks.forEach(drink => {
if(drink.alcohol) {
alcoholDrinks.push(drink);
}
});
});
return alcoholDrinks;
}
getNonAlcoholDrinks(): Drink[] {
let nonAlcoholDrinks: Drink[] = [];
this.getDrinks().subscribe(drinks => {
drinks.forEach(drink => {
if(drink.alcohol === false) {
nonAlcoholDrinks.push(drink);
}
});
});
return nonAlcoholDrinks;
}
setSoldOut(drinkName: string) {
this.drinks.filter((drink) => {
if(drink.name === drinkName) {
drink.soldOut = true;
}
})
}
setDrinks(drinks: Drink[]) {
this.drinks = drinks;
}
}

I can get it to work when, in updateDrinks(), I set the alcoholDrinks as follows

updateDrinks(): void {
    this.alcohols = [{ name: "pintje", alcohol: true, startPrice: 1.5, currentPrice: 1.5, numberSold: 0, numberInOrder: 0, soldOut: false},
    { name: "desperados", alcohol: true, startPrice: 1.5, currentPrice: 2.5, numberSold: 0, numberInOrder: 0, soldOut: false}]
  }

When looking at the logs, the arrays display differently as well. The working solution says (2) [{…}, {…}], and with the non-working version []. I added a screenshot of this here. Apart from that, it all looks the same...

Mat-table不显示数据

The backend (NestJs) function below:

@Get()
    async getDrinks(@Res() res: Response) {
        this.logger.log("GET: getDrinks()")
        res.set('Access-Control-Allow-Origin', 'http://localhost:4200');
        res.send(this.drinksService.getAllDrinks());
    }

Returning this json

[
    {
        "name": "karmeliet",
        "alcohol": true,
        "startPrice": 1.8,
        "numberInOrder": 0,
        "currentPrice": 1.8,
        "numberSold": 0,
        "soldOut": false
    },
    {
        "name": "cola",
        "alcohol": false,
        "startPrice": 1.8,
        "numberInOrder": 0,
        "currentPrice": 1.8,
        "numberSold": 0,
        "soldOut": false
    },
    {
        "name": "test",
        "alcohol": true,
        "startPrice": 1.8,
        "numberInOrder": 0,
        "currentPrice": 1.8,
        "numberSold": 0,
        "soldOut": false
    }
]

答案1

得分: 1

You have an asynchronous issue. 在你在 ngOnInit 中赋值 dataSourceAlcoholdataSourceNonAlcohol 属性的时候,它们的值是空数组,然后在几毫秒后,它们从 API 调用中获取到值。

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

getDrinks() {
   this.drinksService
       .getDrinksByGroup()
       .subscribe(({alcohols, notAlcohols}) => {
          this.alcohols = alcohols;
          this.nonAlcohols = notAlcohols;
          this.dataSourceAlcohol = new MatTableDataSource(this.alcohols);
          this.dataSourceNonAlcohol = new MatTableDataSource(this.nonAlcohols);
   });
}
英文:

You have an asynchronous issue. at the time when you are assigning the dataSourceAlcohol and dataSourceNonAlcohol properties in ngOnInit the values are empty array and after some milliseconds they are getting the values from the API call.

  ngOnInit(): void {
this.updateDrinks();  // <-- you need to wait to get the values from the server and after continue the value assignments
this.dataSourceAlcohol = new MatTableDataSource(this.alcohols);
this.dataSourceNonAlcohol = new MatTableDataSource(this.nonAlcohols);
}

So you need to little bit modify your code in different places:

Let's start.

In drink.service.ts let's remove getAlcoholDrinks and getNonAlcoholDrinks methods and create a new one getDrinksByGroup that will return both (as I understand you are doing the same API call for both.)

  getDrinksByGroup(): Observable<{alcohols: Drink[], notAlcohols: Drink[] }> {
// import map from RxJS operators
return this.getDrinks().pipe(map(drinks => {
const alcoholDrinks: Drink[] = [];
const notAlcoholDrinks: Drink[] = [];
drinks.forEach(drink => {
if(drink.alcohol) {
alcoholDrinks.push(drink);
} else {
notAlcoholDrinks.push(drink)
}
});
return { alcohols: alcoholDrinks, notAlcohols: notAlcoholDrinks };
});
}

in your component let's modify these part of codes(**at first let's remove updateDrinks and let's create the getDrinks method like bellow and also update the code inside ngOnInit **):

  ngOnInit(): void {
this.getDrinks();
}
getDrinks() {
this.drinksService
.getDrinksByGroup()
.subscribe(({alcohols, notAlcohols}) => {
this.alcohols = alcohols;
this.nonAlcohols = notAlcohols;
this.dataSourceAlcohol = new MatTableDataSource(this.alcohols);
this.dataSourceNonAlcohol = new MatTableDataSource(this.nonAlcohols);
});
}

huangapple
  • 本文由 发表于 2023年5月18日 04:32:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76275999.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定