TypeError Can not read property 'name' of undefined in Angular 4

2

My application is working perfectly, the only thing wrong is this error message;

MidiaExibirComponent.html:13 ERROR TypeError: Cannot read property 'nome' of undefined
    at Object.eval [as updateRenderer] (MidiaExibirComponent.html:13)
    at Object.debugUpdateRenderer [as updateRenderer] (core.js:14693)
    at checkAndUpdateView (core.js:13807)
    at callViewAction (core.js:14153)
    at execComponentViewsAction (core.js:14085)
    at checkAndUpdateView (core.js:13808)
    at callViewAction (core.js:14153)
    at execComponentViewsAction (core.js:14085)
    at checkAndUpdateView (core.js:13808)
    at callWithDebugContext (core.js:15056)

Line 13 is this line of code;

<td>{{ cotas.USD.nome }}</td>

This is my full page;

<table class="table">
    <thead>
      <tr>

        <th scope="col">Moedas</th>
        <th scope="col">Valor</th>
        <th scope="col">Visualização</th>
      </tr>
    </thead>
    <tbody>
      <tr>

        <td>{{ cotas.USD.nome }}</td>
        <td>{{ cotas.USD.valor }}</td>
        <td>{{ cotas.USD.ultima_consulta }}</td>
      </tr>
      <tr>

          <td>{{ cotas.EUR.nome }}</td>
          <td>{{ cotas.EUR.valor }}</td>
          <td>{{ cotas.EUR.ultima_consulta }}</td>
      </tr>
      <tr>
          <td>{{ cotas.ARS.nome }}</td>
          <td>{{ cotas.ARS.valor }}</td>
          <td>{{ cotas.ARS.ultima_consulta }}</td>
      </tr>
      <tr>
          <td>{{ cotas.GBP.nome }}</td>
          <td>{{ cotas.GBP.valor }}</td>
          <td>{{ cotas.GBP.ultima_consulta }}</td>
      </tr>

      <tr>
          <td>{{ cotas.BTC.nome }}</td>
          <td>{{ cotas.BTC.valor }}</td>
          <td>{{ cotas.BTC.ultima_consulta }}</td>
      </tr>
    </tbody>
  </table>

This is the service;

import { Midia, Moedas } from './../core/model';

import { Http, Headers, URLSearchParams } from '@angular/http';
import { Injectable } from '@angular/core';

import 'rxjs/add/operator/toPromise';




@Injectable()
export class MidiaService {

  midiasUrl = 'http://localhost:8080/midia/midias';
  quotationURL = 'http://api.promasters.net.br/cotacao/v1/valores?moedas=USD,BTC,EUR,ARS,GBP&alt=json';

  constructor(private http: Http) { }



pesquisarUSD(): Promise<any> {
  return this.http.get('${this.quotationURL}')
  .toPromise()
 .then(response => response.json().valores);

}



}

And that's the component;

import { MidiaService } from './../midia.service';
import { Component, OnInit } from '@angular/core';

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


cotas = [];

  constructor(private midiaService: MidiaService) { }

  ngOnInit() {


      this.pesquisar();
  }

  pesquisar() {
    this.midiaService.pesquisarUSD()
    .then(cotas => this.cotas = cotas);
  }



}

===================================================== ===============

Json file

{
    "status": true,
    "valores": {
        "USD": {
            "nome": "Dólar",
            "valor": 3.408,
            "ultima_consulta": 1523995502,
            "fonte": "UOL Economia - http://economia.uol.com.br/"
        },
        "EUR": {
            "nome": "Euro",
            "valor": 4.2171,
            "ultima_consulta": 1523995502,
            "fonte": "UOL Economia - http://economia.uol.com.br/"
        },
        "ARS": {
            "nome": "Peso Argentino",
            "valor": 0.1691,
            "ultima_consulta": 1523995502,
            "fonte": "UOL Economia - http://economia.uol.com.br/"
        },
        "GBP": {
            "nome": "Libra Esterlina",
            "valor": 4.8704,
            "ultima_consulta": 1523995502,
            "fonte": "UOL Economia - http://economia.uol.com.br/"
        },
        "BTC": {
            "nome": "Bitcoin",
            "valor": 27516,
            "ultima_consulta": 1524047408,
            "fonte": "Mercado Bitcoin - http://www.mercadobitcoin.com.br/"
        }
    }
}

===================================================== ====== See verification code

.then(response => {
  console.log(response.json().valores);

});
}

result of consoles;

===========================================================================

.then(cotas=>{console.log(this.cotas=cotas);});

How do I get this error message?

    
asked by anonymous 18.04.2018 / 14:02

3 answers

2

I had a similar problem, try to write the line this way:

<td>{{ cotas?.USD.nome }}</td> ou <td>{{ cotas.USD?.nome }}</td>
    
18.04.2018 / 14:11
2

Guilherme's answer may work, but I'll suggest an alternative:

At your service, let the method that makes the request return an Observable:

import 'rxjs/add/operator/map';
...
pesquisarUSD(): Observable<any> {
   return this.http.get('${this.quotationURL}').map(response => response.json().valores);
}

In your component, declare the member dimensions as:

import {  share } from 'rxjs/operators';
...
cotasAsync: Observable<{}>;

And in OnInit, look up service data like this:

this.cotasAsync = this.midiaService.pesquisar().pipe(share());

And in the view, do the startup check of the object using pipe async of Angular :

<table class="table" *ngIf="cotasAsync | async; let cota; else loading">
<thead>
  <tr>

    <th scope="col">Moedas</th>
    <th scope="col">Valor</th>
    <th scope="col">Visualização</th>
  </tr>
</thead>
<tbody>
  <tr>

    <td>{{ cota.USD.nome }}</td>
    <td>{{ cota.USD.valor }}</td>
    <td>{{ cota.USD.ultima_consulta }}</td>
  </tr>
  <tr>

      <td>{{ cota.EUR.nome }}</td>
      <td>{{ cota.EUR.valor }}</td>
      <td>{{ cota.EUR.ultima_consulta }}</td>
  </tr>
  <tr>
      <td>{{ cota.ARS.nome }}</td>
      <td>{{ cota.ARS.valor }}</td>
      <td>{{ cota.ARS.ultima_consulta }}</td>
  </tr>
  <tr>
      <td>{{ cota.GBP.nome }}</td>
      <td>{{ cota.GBP.valor }}</td>
      <td>{{ cota.GBP.ultima_consulta }}</td>
  </tr>

  <tr>
      <td>{{ cota.BTC.nome }}</td>
      <td>{{ cota.BTC.valor }}</td>
      <td>{{ cota.BTC.ultima_consulta }}</td>
  </tr>
</tbody>
</table>

Some suggestions: - If using Angular 4 or higher, start using the HttpClient class instead of Http. The Http class is obsolete.

    
18.04.2018 / 17:11
2

Probably because the view is trying to display something that does not already exist, even before the HTTP request starts:

<td>{{ cotas.USD.nome }}</td>
<td>{{ cotas.USD.valor }}</td>
<td>{{ cotas.USD.ultima_consulta }}</td>

That is, the message:

  

Can not read property 'name' of undefined

It says that you tried to name undefined , this means that: contas.USD , contas.EUR , etc, are nonexistent keys within your this.contas object, what you could use is simply *ngIf ( link ) to check if the value exists:

  <tr *ngIf="cotas.USD">
    <td>{{ cotas.USD.nome }}</td>
    <td>{{ cotas.USD.valor }}</td>
    <td>{{ cotas.USD.ultima_consulta }}</td>
  </tr>

  <tr *ngIf="cotas.EUR">
      <td>{{ cotas.EUR.nome }}</td>
      <td>{{ cotas.EUR.valor }}</td>
      <td>{{ cotas.EUR.ultima_consulta }}</td>
  </tr>

  <tr *ngIf="cotas.ARS">
      <td>{{ cotas.ARS.nome }}</td>
      <td>{{ cotas.ARS.valor }}</td>
      <td>{{ cotas.ARS.ultima_consulta }}</td>
  </tr>

  <tr *ngIf="cotas.GBP">
      <td>{{ cotas.GBP.nome }}</td>
      <td>{{ cotas.GBP.valor }}</td>
      <td>{{ cotas.GBP.ultima_consulta }}</td>
  </tr>

  <tr *ngIf="cotas.BTC">
      <td>{{ cotas.BTC.nome }}</td>
      <td>{{ cotas.BTC.valor }}</td>
      <td>{{ cotas.BTC.ultima_consulta }}</td>
  </tr>

You could also iterate this.cotas with *ngFor= so you would not have to do as much code repetition using let cota of cotas , so cota will loop through USD, EUR, ARS, GBP and BTC: / p>

<table class="table">
    <thead>
      <tr>

        <th scope="col">Moedas</th>
        <th scope="col">Valor</th>
        <th scope="col">Visualização</th>
      </tr>
    </thead>
    <tbody>

      <tr *ngFor="let cota of cotas">
          <td>{{ cota.nome }}</td>
          <td>{{ cota.valor }}</td>
          <td>{{ cota.ultima_consulta }}</td>
      </tr>

    </tbody>
  </table>

This helps to greatly decrease the code.

    
18.04.2018 / 16:57