Home > Enterprise >  Failed to display data from Http get request in a mat-table
Failed to display data from Http get request in a mat-table

Time:07-18

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.

This is what I get

So I went back to the backend code to change the returned data as an Array of String ( List ) --> in this case I receive this result 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

  • Related