Show Page from Springboot at angle 6 using Angular Material Data Table

Asked

Viewed 336 times

0

Hello, I’m starting in angular and would like to show the result of a search that is coming from an api I built using springboot. my Sponse is coming like this:

{,…}
content: [{id: 33, dsProjeto: "teste", nomeProjeto: "nometeste", setor: "Insurance",…},…]
0: {id: 33, dsProjeto: "teste2", nomeProjeto: "nometeste2", setor: "Insurance",…}
1: {id: 36, dsProjeto: "teste3", nomeProjeto: "nometeste3",…}
2: {id: 37, dsProjeto: "teste4", nomeProjeto: "nometeste4",…}
3: {id: 38, dsProjeto: "teste5", nomeProjeto: "nometeste5", setor: "Industry",…}
empty: false
first: true
last: true
number: 0
numberOfElements: 4
pageable: "INSTANCE"
size: 0
sort: {sorted: false, unsorted: true, empty: true}
totalElements: 4
totalPages: 1

The api is returning a Page, the problem is that I need to show it on the front and I don’t know how it does. I followed some tutorials, but it’s not working. The following error appears on the console: Cannot read Property 'content' of Undefined. And really, when I give a console.log on date in the.Component statement onInit, after the subscribe, date appears as Undefined. However, as I said above, my service is returning the right answer. In the network tab of Rome, the answer is right. Could someone help me? Follow my angular codes:

attested.component.html:

<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">
<!-- Id Column -->
<ng-container matColumnDef="id">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
  <td mat-cell *matCellDef="let element"> {{element.id}} </td>
</ng-container>

<ng-container matColumnDef="dsProjeto">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> DsProjeto </th>
  <td mat-cell *matCellDef="let element"> {{element.dsProjeto}} </td>
</ng-container>

<ng-container matColumnDef="nomeGerente">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> Nome Gerente </th>
  <td mat-cell *matCellDef="let element"> {{element.nomeGerente}} </td>
</ng-container>

<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

attested.component.ts:

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
import { ProjetoService } from 'src/app/shared/services/projeto.service';
import { Atestado, Page } from './atestado';

@Component({
   selector: 'app-atestado',
   templateUrl: './atestado.component.html',
   styleUrls: ['./atestado.component.scss']
 })
 export class AtestadoComponent implements OnInit {

 dataSource: MatTableDataSource<Atestado>;
 displayedColumns= ['id', 'dsProjeto', 'nomeGerente'];
 page: Page;

 @ViewChild(MatSort) sort: MatSort;
 @ViewChild(MatPaginator) paginator: MatPaginator;   

 constructor(private projetoService: ProjetoService) {}

 ngOnInit(): void {
    this.projetoService.buscaAtestados('java',1,'id','ASC')
    .subscribe(
        data  => {
            console.log(data);
            this.page = data;
            const atestados = data.content;
            this.dataSource = new MatTableDataSource<Atestado>(atestados);
        });
 }
}

project.service.ts:

import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from "rxjs/operators";
import { mappingUrls } from src/app/shared/commons/constants/constants.service';
import { environment } from '../../../environments/environment';
import { GenericService } from './generic.service';

@Injectable({
  providedIn: 'root'
})
export class ProjetoService {
   private applicationUrl = 'http://' + environment.host + ':' + environment.port + '/api/';

 constructor(private httpClient: HttpClient, private genericService: GenericService) {}

 public buscaAtestados(filtro,page,size): Observable<Page> {

return  this.httpClient.get<Atestado>(this.applicationUrl + mappingUrls.projetoService.buscaAtestados, { 
    params: new  HttpParams ()
        .set('filtro',filtro)
        .set('page',page.toString())
        .set('size',size.toString())
}).pipe(
        map(res =>  res["payload"])
    );
}

the attested interface.ts

export interface Page {
  content: Atestado[];
  pageable: string;
  totalElements: number;
  last: boolean;
  totalPages: number;
  size: number;
  number: number;
  sort: Sort;
  numberOfElements: number;
  first: boolean;
  empty: boolean;
}

export interface Sort {
  sorted: boolean;
  unsorted: boolean;
  empty: boolean;
}

export interface Atestado {
  id: string;
  dsProjeto: string;
  setor: string;
  un: string;
  dtInicio: string;
  //codigo omitido
}

I appreciate the help!

2 answers

1

I managed to resolve, as I am returning a Page from my Api, the observable had to be of the Page type .. The error was in my service. Follows corrected code:

 public buscaAtestados( 
            filtro: string,
            page: number,
            ord:string,
            dir:string): Observable<Page> {

    return  this.httpClient
    .get<Page>(this.applicationUrl + mappingUrls.projetoService.buscaAtestados, { 
    params: new  HttpParams ()
        .set('filtro',filtro)
        .set('pag',page.toString())
        .set('ord',ord)
        .set('dir', dir)
    }).pipe(
        map(res => {
            return res;
        })
    );
}

0


The lines you want to show are on content of the answer object. You need to read this correctly. I suggest that you create a class from the JSON of the answer, of JSON all because you will need it later to make the pagination. This article you used is a great reference.

To create the JSON, if using the Vscode, use the plugin Jsontots JSONToTS. Then in the GET, make the typed return:

public buscaAtestados(filtro,page,size): Observable<any[]> {

return  this.httpClient.get<IResult>(this.applicationUrl + mappingUrls.projetoService.buscaAtestados, { 
    params: new  HttpParams ()
        .set('filtro',filtro)
        .set('page',page.toString())
        .set('size',size.toString())
}).pipe(
        map(res =>  res["payload"])
    );
}

In his dataSource, take only the content for the data:

this.projetoService.buscaAtestados(filter, pageIndex, pageSize).pipe(
        catchError(() => of([])),
        finalize(() => this.loadingSubject.next(false))
    )
    .subscribe( (atestados: IResult) => this.atestadoSubject.next(atestados.content));

EDITED

Your class as JSON would look like this: inserir a descrição da imagem aqui

  • hi, thanks for the answer! I’m not sure I understand what you meant about creating a class from json. I’m not using vscode... but, from what I understand, would it be for me to create a class with the attributes that come in my json? Well, that’s what I did, and posted the changes, created an attested interface.ts. However, in my datasource, in the part of getting the content, it does not recognize . content as a method and does not even compile. I’m sorry if I misunderstood what you meant.

  • Your interface was incomplete, I added a print of how it would look from the JSON which you provided in your question. Note that she has the property Content, an array, which I understood to be the data you want to display on data-tabland.

  • Hi! Thanks for the help again! I changed my interface. I used the web version of Jsont ts. I also changed some things in my service that started to return an Observable<Page> and also made modifications of my datasource. But even so, it’s not showing anything.. have you any idea what it is? I believe my datasource is wrong now, but I don’t know where.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.