英文:
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:
-
Ensure that the API call is successfully fetching the data by adding console logs in your component to see the response from the API.
-
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...
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
中赋值 dataSourceAlcohol
和 dataSourceNonAlcohol
属性的时候,它们的值是空数组,然后在几毫秒后,它们从 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);
});
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论