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

this._negociacoes is undefined

Boa tarde, cheguei no módulo 4 e ao finalizar o método responsável por importar dados recebi a seguinte mensagem no console:

this._negociacoes is undefined

Segue o código do meu controlador:

import { Negociacao, Negociacoes } from "../models/index";
import { NegociacoesView, MensagemView } from "../views/index";
import { domInject } from "../helpers/decorators/domInject";

export class NegociacaoController {

    @domInject('#data')
    private _inputData: JQuery;

    @domInject('#quantidade')
    private _inputQuantidade: JQuery;

    @domInject('#valor')
    private _inputValor: JQuery;

    private _negociacoes: Negociacoes = new Negociacoes();
    private _negociacoesView : NegociacoesView = new NegociacoesView('#negociacoesView');
    private _mensagemView : MensagemView = new MensagemView('#mensagemView');

    constructor() {

        //this._inputData = $('#data');
        //this._inputQuantidade = $('#quantidade');
        //this._inputValor = $('#valor');
        this._negociacoesView.update(this._negociacoes);

    }

    adiciona(event:Event) {

        event.preventDefault();

        const negociacao = new Negociacao(
            new Date(this._inputData.val().replace(/-/g, ',')),
            parseInt(this._inputQuantidade.val()),
            parseFloat(this._inputValor.val())
        );

        this._negociacoes.adiciona(negociacao);
        this._negociacoesView.update(this._negociacoes);
        this._mensagemView.update('Negociação Inserida com Sucesso!');
    }

    importarDados() {

        function isOK(res: Response) {

            if(res.ok) {
                return res;
            } else {
                throw new Error(res.statusText);
            }
        }

        fetch('http://localhost:8080/dados')
            .then(res => isOK(res))
            .then(res => res.json())
            .then((dados: any[]) => {
                dados
                    .map(dado => new Negociacao(new Date(), dado.vezes, dado.montante))
                    .forEach(negociacao => this._negociacoes.adiciona(negociacao));

            })
            .catch(err => console.log(err.message));       
    }

}
11 respostas

Alguém? Tem algo errado com o escopo dessas variáveis é como se as variáveis:

    private _negociacoes = new Negociacoes();
    private _negociacoesView = new NegociacoesView('#negociacoesView');
    private _mensagemView = new  MensagemView('#mensagemView');
    private _service = new NegociacaoService();

não pudesse ser utilizadas dentro do escopo do foreach. Testo tanto no FF quanto no Chrome e não funciona o código que importa.

solução!

Olá, Heric.

O erro this._negociacoes is undefined está dando em qual linha do seu código?

Ah! Por favor, você pode posta a classe do seu objeto Negociacoes pra ver se há algum erro por lá?

Olá Marco, segue a minha classe Negociações:

import { Negociacao } from "./Negociacao";

export class Negociacoes {
    private _negociacoes : Array<Negociacao> = [];

    public adiciona(negociacao : Negociacao) : void {
        this._negociacoes.push(negociacao);
    }

    public paraArray() : Negociacao[]  {
        return ([] as Negociacao[]).concat(this._negociacoes);
    }
}

quanto a linha que deu erro:

 .forEach(negociacao => this._negociacoes.adiciona(negociacao));

é como se this.negociacoes não fosse permitido utilizar dentro do escopo do forEach. Porque se eu mudar para:

.forEach(negociacao => console.log(negociacao)  );

todos os objetos são exibidos.

Eric. Troque a arrow function pra uma função anônima, dentro do forEach:

forEach(function(negociacao) {
    this._negociacoes.adiciona(negociacao)
});

Ainda sim não funcionou eu peguei o código disponibilizado pelo o Alura mas mesmo assim não funciona segue:

import { NegociacoesView, MensagemView } from '../views/index';
import { Negociacao, Negociacoes } from '../models/index';
import { domInject } from '../helpers/decorators/index';

export class NegociacaoController {

    @domInject('#data')
    private _inputData: JQuery;

    @domInject('#quantidade')
    private _inputQuantidade: JQuery;

    @domInject('#valor')
    private _inputValor: JQuery;

    private _negociacoes = new Negociacoes();
    private _negociacoesView = new NegociacoesView('#negociacoesView');
    private _mensagemView = new MensagemView('#mensagemView');

    constructor() {
        this._negociacoesView.update(this._negociacoes);
    }

    adiciona(event: Event) {

        event.preventDefault();

        let data = new Date(this._inputData.val().replace(/-/g, ','));

        if(!this._ehDiaUtil(data)) {

            this._mensagemView.update('Somente negociações em dias úteis, por favor!');
            return 
        }

        const negociacao = new Negociacao(
            data, 
            parseInt(this._inputQuantidade.val()),
            parseFloat(this._inputValor.val())
        );

        this._negociacoes.adiciona(negociacao);

        this._negociacoesView.update(this._negociacoes);
        this._mensagemView.update('Negociação adicionada com sucesso!');
    }

    private _ehDiaUtil(data: Date) {

        return data.getDay() != DiaDaSemana.Sabado && data.getDay() != DiaDaSemana.Domingo;
    }

    importarDados() {

        function isOK(res: Response) {

            if(res.ok) {
                return res;
            } else {
                throw new Error(res.statusText);
            }
        }

        fetch('http://localhost:8080/dados')
            .then(res => isOK(res))
            .then(res => res.json())
            .then((dados: any[]) => {
                dados
                    .map(dado => new Negociacao(new Date(), dado.vezes, dado.montante))
                    .forEach(
                        function(negociacao) {
                            this._negociacoes.adiciona(negociacao); //Não encontra no escopo esse this._negociacoes
                        }
                    );

            })
            .catch(err => console.log(err.message)); 

    }
}

enum DiaDaSemana {

    Domingo, 
    Segunda, 
    Terca, 
    Quarta, 
    Quinta, 
    Sexta, 
    Sabado
}

O erro no firefox é:

this._negociacoes is undefined

O erro no Chrome é:

Cannot read property 'adiciona' of undefined

Eric, por favor dentro da função anônima do seu forEach coloca um console.log(this) e me diz o que retorna?

Olá Marco, fiz duas alterações no código acima:

console.log(negociacao);
 console.log(this);

a saída foi:

Object { data: Date 2018-01-19T00:10:13.244Z, quantidade: 2, valor: 200.5 }
NegociacaoController.js:62:29
undefined
NegociacaoController.js:63:29
Object { data: Date 2018-01-19T00:10:13.244Z, quantidade: 5, valor: 100.2 }
NegociacaoController.js:62:29
undefined
NegociacaoController.js:63:29
Object { data: Date 2018-01-19T00:10:13.244Z, quantidade: 1, valor: 50.5 }
NegociacaoController.js:62:29
undefined
NegociacaoController.js:63:29
Object { data: Date 2018-01-19T00:10:13.244Z, quantidade: 2, valor: 70.5 }
NegociacaoController.js:62:29

undefined <<<<<

como eu posso acessar os atributos privados com o this?

Eric. A forma mais simples é criar um variável no método importarDados que referencie o this do objeto:

importarDados() {
    const origin = this;
        function isOK(res: Response) {

            if(res.ok) {
                return res;
            } else {
                throw new Error(res.statusText);
            }
        }

        fetch('http://localhost:8080/dados')
            .then(res => isOK(res))
            .then(res => res.json())
            .then((dados: any[]) => {
                dados
                    .map(dado => new Negociacao(new Date(), dado.vezes, dado.montante))
                    .forEach(
                        function(negociacao) {
                            origin._negociacoes.adiciona(negociacao); //Não encontra no escopo esse this._negociacoes
                        }
                    );

            })
            .catch(err => console.log(err.message)); 

    }

Acredito que isso funcionará :-)

Bom dia,

fiz todas as alterações possíveis conforme sugerido e mesmo assim não funciona a importação. Além disso, fiz em duas máquinas diferentes. Porém, eu instalei o mesmo Node (v6.12.2) nelas. A única esperança é mudar a versão do Node.

Update:

Atualizei o Node para última versão. Refiz o código conforme a vídeo aula e não entendo o motivo de não conseguir importar esses dados. O código está idêntico ao do professor.

No chrome:

Cannot read property 'adiciona' of undefined

No Firefox:

origin._negociacoes is undefined (conforme código sugerido acima)

update2:

no log de compilação encontrei essa mensagem:

[0] app/ts/controllers/NegociacaoController.ts(72,34): error TS2339: Property '_negociacoes' does not exist on type 'void'. [0] 20:17:29 - Compilation complete. Watching for file changes.

Sugiro colocar toda a configuração exatamente como foi utilizado no curso. Parei o curso pois não consigo importar os dados.

Suba seu código no github pois ele precisa ser visto por inteiro. Digo isso porque mais de 1200 alunos chegaram ao fim sem problema algum.

Aguardo o código do repositório. ( ou algum link com ele zipado).

Aliás...como você associou o método do controller ao clique do botão? Se não fez bind igual você aprende no curso pré requisito deste curso não irá funcionar. Alias, para programar em TS você precisa saber ES6. Vi que não fez o curso pré requisito. Seu aproveitamento será muito melhor se fizer.

import { NegociacaoController } from './controllers/NegociacaoController';

const controller = new NegociacaoController();
$('.form').submit(controller.adiciona.bind(controller));

//você fez assim???
$('#botao-importa').click(controller.importarDados.bind(controller)); // se você não fez assim não vai funcionar porque this não será a instância do controller.

Se usar função anônima no foreach também não vai funcionar, tem que ser arrow function pelo this léxico.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software