I'm fetching data from an API; a Http get request. The returned data that I'm having is Object composed of 02 Strings and 03 Integer. I do receive the data in the console (from the "AuthenticationService"), but I failed displaying them in the material table; mat-table.
So I went back to the backend code to change the returned data as an Array of String ( List ) --> in this case I receive Even the same row duplicated 05 times !!
Here is my ts file:
import { HttpClient } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Device } from '../models/Device';
import { DeviceMi } from '../models/DeviceMi';
import { AuthenticationService } from '../service/authentication.service';
@Component({
selector: 'app-mi',
templateUrl: './mi.component.html',
styleUrls: ['./mi.component.css']
})
export class MiComponent implements OnInit {
miToDisplay: any;
displayedColumns: string[] = ['fabrNumberModel', 'deviceNameModel', 'deviceStateModel', 'deviceTypeModel', 'deviceTemperatureModel', 'actions'];
data3: any;
dataSource!: MatTableDataSource<DeviceMi>;
itemsPerPage: number = 10;
row: any;
@ViewChild('paginationMiDevicesListing') paginator!: MatPaginator;
@ViewChild('sortDevicesListing') sort!: MatSort;
constructor(
private responseService: AuthenticationService,
) { }
ngOnInit() {
this.dataSource = new MatTableDataSource(this.miToDisplay);
this.dataSource.paginator = this.paginator;
this.displayMiDevices();
}
displayMiDevices() {
this.data3 = localStorage.getItem('accessToken');
console.log(this.data3);
this.responseService.getV1Devices().subscribe( data => {
console.log(data);
this.miToDisplay = data;
console.warn(this.miToDisplay);
}
);
console.log(this.miToDisplay);
}
}
Here is the html file:
<div >
<mat-table [dataSource]="miToDisplay" matSort>
<!-- Mi Device Id Column -->
<ng-container matColumnDef="fabrNumberModel">
<mat-header-cell *matHeaderCellDef mat-sort-header> Mi Device ID </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.fabrNumberModel}} </mat-cell>
</ng-container>
<!-- Device Name Column -->
<ng-container matColumnDef="deviceNameModel">
<mat-header-cell *matHeaderCellDef mat-sort-header> Device Name </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.deviceNameModel}} </mat-cell>
</ng-container>
<!-- Device State Column -->
<ng-container matColumnDef="deviceStateModel">
<mat-header-cell *matHeaderCellDef mat-sort-header> Device State </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.deviceStateModel}} </mat-cell>
</ng-container>
<!-- Device Type Column -->
<ng-container matColumnDef="deviceTypeModel">
<mat-header-cell *matHeaderCellDef mat-sort-header> Device Type </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.deviceTypeModel}} </mat-cell>
</ng-container>
<!-- Device Temperature Column -->
<ng-container matColumnDef="deviceTemperatureModel">
<mat-header-cell *matHeaderCellDef mat-sort-header> Device Temperature </mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.deviceTemperatureModel}} </mat-cell>
</ng-container>
<!-- Button Column -->
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef><mat-icon>power_settings_new</mat-icon></th>
<mat-cell *matCellDef="let row">
<mat-slide-toggle (click)="powerOnAction(row)"></mat-slide-toggle>
<mat-icon>power_on</mat-icon>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator #paginationMiDevicesListing [length]="50" [pageSizeOptions]="[5, 10, 20]"
showFirstLastButtons
aria-label="Select page of periodic elements"
showFirstLastButtons=>
</mat-paginator>
</div>
Here is the AuthenticationService that has the Http get request:
getV1Devices(): Observable<any> {
return this.httpServiceAuthentication.get<any>(this.url2);
}
How can I resolve this and display the data in the table? iIn my case I should see one row in the table. Thanks.
CodePudding user response:
You are assigning this.dataSource = new MatTableDataSource(this.miToDisplay);
before this.miToDisplay
is filled with data coming from the API.
To overcome this problem, you have to reinit this.dataSource
inside your .subscribe()
block.
displayMiDevices() {
this.data3 = localStorage.getItem('accessToken');
console.log(this.data3);
this.responseService.getV1Devices().subscribe((data) => {
console.log(data);
this.miToDisplay = data;
console.warn(this.miToDisplay);
this.dataSource = new MatTableDataSource(this.miToDisplay); // HERE
});
console.log(this.miToDisplay);
}
Also in your .html
you don't bind your mat-table
dataSource
attribute with the variable itself. <mat-table [dataSource]="miToDisplay" matSort>
<< This is wrong. You need to instead bind it with the dataSource
instead.
Like this <mat-table [dataSource]="dataSource" matSort>
CodePudding user response:
I maintained the Json response as a json (in the backend):
public Response fetchV1Devices(.....) {
// some code here
retrun Response.ok(js).build();
}
then I converted it to an Array like this this.dataSource = new Array(data);
and of course in the html file <mat-table [dataSource]=dataSource matSort>
so it becomes like this:
this.responseService.getV1Devices().subscribe( data => {
this.miToDisplay = data;
this.dataSource = new Array(data);
}
);
This topic is similar to the issue: Provided data source did not match an array, Observable, or DataSource at getTableUnknownDataSourceError