Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Como faço para o arquivo *.component.html reconhecer meu arquivo *.component.ts sem um controller?

Flávio, criei um serviço e o meu arquivo dashboard.component.ts está recuperando corretamente meu array de objetos. Entretanto, não consigo fazer com que estes objetos sejam apresentados em uma tabela no arquivo HTML. Sinto falta de informar o controller e não sei como resolver isso. Fiz o ngFor como ensinado na aula, mas pra mim não funcionou.

Ressalto que se eu criar o "rankingVendedores: Object[] = [];" no arquivo dashboard.component.ts e no meu private chamar como "this.rankingVendedores", o console deixa de imprimir meu array de objetos, gerando os erros:

dashboard.component.ts:189 An error occurred TypeError: Cannot set property 'rankingVendedores' of undefined

ERROR Error: Uncaught (in promise): Cannot set property 'rankingVendedores' of undefined

Envio a seguir meus códigos para verificar o que posso ter feito de errado.

SERVIÇO

import 'rxjs/add/operator/toPromise';
import { Injectable } from '@angular/core';
import { Http, Response, Headers, URLSearchParams, RequestOptions } from '@angular/http';

@Injectable()
export class DashboardService {

  headers: Headers;
  options: RequestOptions;
  params: URLSearchParams;

  constructor(private http: Http) {
    this.headers = new Headers({ 'Content-Type': 'application/json', 
                                 'Authorization': 'xxx'});

    let params = new URLSearchParams();
    params.append('tipoRanking', 'Valor');
    params.append('quantidadeRanking', '10');
    params.append('inicioPeriodo', '2017-03-28T14:24:10.016Z');
    params.append('fimPeriodo', '2018-03-28T14:24:10.016Z');

    this.options = new RequestOptions({ headers: this.headers, params: params });
  }

  getService(url: string): Promise<any> {
    return this.http
      .get(url, this.options)
      .toPromise()
      .then(this.extractData)
      .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body || {};
  }

  private handleError(error: any): Promise<any> {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
  }

}

TS

import { Component, OnInit } from '@angular/core';
import { DashboardService } from './dashboard.service';
import { Http, Response, Headers, URLSearchParams, RequestOptions } from '@angular/http';

@Component({
  moduleId: module.id,
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

  constructor(private dashboardService: DashboardService) { }

  ngOnInit() {
    this.dashboardService
    .getService('http://.../v2/API/Consulta/ServicoConsulta.svc/consultarRankingClientes')
    .then(this.extractData)
    .catch(this.handleError);
  }

  private extractData(res: any) {
    let rankingVendedores = res.Objetos;
    return console.log(res);
  }

  private handleError(error: any): Promise<any> {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
  }

HTML

<table>
...
<tbody>
    <tr *ngFor="let rankingVendedor of rankingVendedores">
        <td>{{rankingVendedor.Nome}}</td>
        <td>{{rankingVendedor.ValorVendido}}</td>
    </tr>
</tbody>
</table>

CONSOLE.LOG

No meu console, ao fazer um debug no arquivo *.component.ts, a "rankingVendedores" recebe corretamente as informações, só não sei porque o HTML não recebe.

Object
> Excecoes:[]
> Objetos: Array(10)
0: {Codigo: "000003", Nome: "NOME A", ValorVendido: 104628.2568}
1: {Codigo: "000009", Nome: "NOME B", ValorVendido: 50807.815}
7 respostas

Olá Thainá, o problema é que você não declarou a variável rankingVendedores no escopo global do seu componente, faça isso:

import { Component, OnInit } from '@angular/core';
import { DashboardService } from './dashboard.service';
import { Http, Response, Headers, URLSearchParams, RequestOptions } from '@angular/http';

@Component({
  moduleId: module.id,
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {

rankingVendedores = [];
  constructor(private dashboardService: DashboardService) { }

  ngOnInit() {
    this.dashboardService
    .getService('http://.../v2/API/Consulta/ServicoConsulta.svc/consultarRankingClientes')
    .then(this.extractData)
    .catch(this.handleError);
  }

  private extractData(res: any) {
    rankingVendedores = res.Objetos;
    return console.log(res);
  }

  private handleError(error: any): Promise<any> {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
  }

espero ter ajudado, bons estudos! ;)

Olá Jeferson,

Na verdade eu tentei isso também e ocorre os erros:

dashboard.component.ts:189 An error occurred TypeError: Cannot set property 'rankingVendedores' of undefined

ERROR Error: Uncaught (in promise): Cannot set property 'rankingVendedores' of undefined

Boa tarde a todos!

Jeferson, o seu código não está correto! Como rankingVendedores é um atributo, deveria ser feito assim:

private extractData(res: any) {
    this.rankingVendedores = res.Objetos;
    return console.log(res);
}

Thainá, verifique se com essa modificação que sugeri o seu problema é resolvido. Se não resolver, me diz uma coisa: o que tem na linha 189 do arquivo dashboard.component.ts que é a linha onde está dando erro?

Olá Gabriel,

Eu já havia feito essa alteração no código do Jeferson, mas não funcionou.

O que tem na linha 189 é a linha do console de erro: console.error('An error occurred', error);

Código completo:

private handleError(error: any): Promise<any> {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
}

Sinalizo também que declarando "rankingVendedores = [];" como sugerido, "this.rankingVendedores" deixa de receber o array de objetos dentro do private. Ele só recebe o array de objetos se eu fizer:

private extractData(res: any) {
    let rankingVendedores = res.Objetos;
    return console.log(res);
}

Entendi. Mas o que acho estranho é que a mensagem diz

ERROR Error: Uncaught (in promise): Cannot set property 'rankingVendedores' of undefined

Mas, em nenhum momento do código que vc postou aqui vc tenta fazer um set de tal propriedade. Eu imagino que o problema está em algum ponto do código que vc está omitindo.

O código omitido são gráficos Highcharts comentados. Comentei tudo justamente pra ver se o problema vinha deles, mas não é o caso.

Essa segunda mensagem é porque tentei fazer o seguinte:

private handleError(error: any): Promise<any> {
    console.error('An error occurred', error);
    return Promise.reject(error.message || error);
}

A mensagem que está gerando toda essa dor de cabeça é:

An error occurred TypeError: Cannot set property 'rankingVendedores' of undefined                    webpack-internal:///./src/app/dashboard/dashboard.component.ts:31
    at DashboardComponent.extractData (webpack-internal:///./src/app/dashboard/dashboard.component.ts:27)
    at ZoneDelegate.invoke (webpack-internal:///./node_modules/zone.js/dist/zone.js:388)
    at Object.onInvoke (webpack-internal:///./node_modules/@angular/core/esm5/core.js:4965)
    at ZoneDelegate.invoke (webpack-internal:///./node_modules/zone.js/dist/zone.js:387)
    at Zone.run (webpack-internal:///./node_modules/zone.js/dist/zone.js:138)
    at eval (webpack-internal:///./node_modules/zone.js/dist/zone.js:858)
    at ZoneDelegate.invokeTask (webpack-internal:///./node_modules/zone.js/dist/zone.js:421)
    at Object.onInvokeTask (webpack-internal:///./node_modules/@angular/core/esm5/core.js:4956)
    at ZoneDelegate.invokeTask (webpack-internal:///./node_modules/zone.js/dist/zone.js:420)
    at Zone.runTask (webpack-internal:///./node_modules/zone.js/dist/zone.js:188)

Observe que apaguei tudo, então não é mais a linha 189 é a 31, que ainda é o console de erro.

solução!

Então pessoal, o problema foi o private na resposta. Mantive a declaração global e apenas retirei o private da resposta; mantive o private apenas no erro e deu certo pra mim. Obrigada a todos que ajudaram!

ngOnInit() {
  this.dashboardService
  .getService('http://.../svc/consultarRankingVendedores')
  .then(res => {
      this.rankingVendedores = res.Objetos;
    })
  .catch(this.handleError);
  }

  private handleError(error: any) {
    console.error('An error occurred', error);
    return (error.message || error);
  }