HTML being built before the return of the Angular api

Asked

Viewed 81 times

0

I want to receive data from my API and build cards with them dynamically, so I’m using Angular’s 'Binding', but my HTML is being built before the answer is completed, so it’s seen as Undefined. I’ve tried using prefixes, but unsuccessfully, I’ve also tried using ngIf to only generate the cards when my variable has value, again unsuccessfully.

Service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { IDisciplina } from 'src/app/shared/models/IDisciplina';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DisciplinaService {

  private UrlBase = 'http://localhost:5000/api/disciplina';

  constructor(private http: HttpClient) { }

  getDisciplinaById(Id: number): Observable<IDisciplina[]>  {
    return this.http.get<IDisciplina[]>(`${this.UrlBase}/${Id}`);
  }

  getDisciplinaByTurma(TurmaId: number): Observable<IDisciplina[]>  {
    return this.http.get<IDisciplina[]>(`${this.UrlBase}/getByTurma/${TurmaId}`);
  }

}

Component.

import { Component, OnInit } from '@angular/core';
import { DisciplinaService } from 'src/app/core/services/Disciplina/Disciplina.service';
import { IDisciplina } from 'src/app/shared/models/IDisciplina';

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

  DisciplinaPorTurma: IDisciplina[];

  constructor(private disciplinaService: DisciplinaService) {}

  ngOnInit() {
    this.ReceberDisciplinas();
    console.log(this.DisciplinaPorTurma);
  }

  ReceberDisciplinas() {
    this.disciplinaService.getDisciplinaByTurma(2).subscribe(
      (Disciplina: IDisciplina[]) => this.DisciplinaPorTurma = Disciplina,
      error => console.log('Falha na chamada. Erro: ' + error),
      () => console.log('Chamada a API finalizada!'));
  }

}

HTML

<app-toolbar Titulo="UnipClassroom" LadoDireito="Henrique de Castro"></app-toolbar>
<div *ngIf="DisciplinaPorTurma">
  <app-spinner></app-spinner>
</div>
<div *ngIf="!DisciplinaPorTurma">
  <div class="container" *ngFor="let Disciplina of DisciplinaPorTurma">
    <div class="row">
      <div class="col-sm-6 col-md-4 col-lg-3">
        <mat-card class="tamanho-card margin-card mb-4">
          <mat-card-header>
            <mat-card-title>{{Disciplina.Nome}}</mat-card-title>
            <mat-card-subtitle>{{Disciplina.CursoId}}</mat-card-subtitle>
          </mat-card-header>
        </mat-card>
      </div>
    </div>
  </div>
</div>
  • Instead of giving a subscribe in service in HomeComponent.ts, assigns the variable Disciplinaporturma: as being of the type Observable<IDisciplina[]> and in the loop of Html leaves with a async pipe thus *ngFor="let Disciplina of DisciplinaPorTurma | async"

  • I made two mistakes doing that. First no subscribe: "Type 'Idisciplina[]' is Missing the following properties from type 'Observable<Idisciplina[]>': _isScalar, source, Operator, lift, and 5 more.ts(2740)" The second was with pipe: " Invalidpipeargument: '[Object Object]' for pipe 'Asyncpipe''"

1 answer

0


you were in the right direction. The detail our friend said of using the pipe async is valid. The first moment is a bit confusing anyway, but come on. First change the type of your attribute to a observable

DisciplinaPorTurma$: Observable<IDisciplina[]>;

After that change your query method to:

ReceberDisciplinas() {
   this.DisciplinaPorTurma$ = this.disciplinaService.getDisciplinaByTurma(2);
}

Even this approach is a good practice to avoid possible memory leaks (memory Leak). Made these changes to your ts file, now just add the async pipe to your template.

<div class="container" *ngFor="let Disciplina of DisciplinaPorTurma$ | async">
   <!-- Conteúdo aqui -->
</div>

To facilitate understanding, I set an example in stackblitz

Browser other questions tagged

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