Solucionado (ver solução)

Importante

Você está vendo a versão anterior da nova experiência da Alura que estamos preparando para você. Em breve, ela ganha uma identidade visual novinha totalmente pensada em potencializar seus estudos!

Solucionado
(ver solução)
10
respostas

Erro na atualização da view de mensagem

Estou com problemas no item 3 da aula 3. Fiz todo o código como está no vídeo, porém não estou conseguindo obter o resultado. Minhas mensagens não aparecem corretamente de acordo com a ação que fiz. A primeira nunca vai, às vezes aparece "Adicionado com sucesso" quando apago e "Apagado com sucesso" quando adiciono. Alguma sugestão?

NegociacaoController.js

class NegociacaoController {

    constructor() {
        let $ = document.querySelector.bind(document);

        // A chamada dentro de um construtor para os input's evita percorrer o DOM várias vezes
        this._inputData = $('#data');
        this._inputQuantidade = $('#quantidade');
        this._inputValor = $('#valor');

        this._negociacoesView = new NegociacoesView($('#negociacoesView'));
        this._listaNegociacoes = new Bind(
            new ListaNegociacoes(),
            this._negociacoesView,
            ['adiciona', 'esvazia']
        );

        this._mensagemView = new MensagemView($('#mensagemView'));
        this._mensagem = new Bind(
            new Mensagem(),
            this._mensagemView,
            ['texto']
        );

    }

    adiciona(event) {
        event.preventDefault();

        this._listaNegociacoes.adiciona(this._criaNegociacao());
        this._mensagem.texto = 'Negociação adicionada com sucesso';
        this._limpaFormulario();
    }

    apaga() {

        this._listaNegociacoes.esvazia();
        this._mensagem.texto = 'Negociações apagadas com sucesso!';
    }

    _criaNegociacao() {

        return new Negociacao(
            DateHelper.textoParaData(this._inputData.value),
            this._inputQuantidade.value,
            this._inputValor.value
        );
    }

    _limpaFormulario() {
        this._inputData.value = '';
        this._inputQuantidade.value = 1;
        this._inputValor.value = 0.0;

        this._inputData.focus();
    }
}

Bind.js

class Bind{

    constructor(model, view, props){

        let proxy = ProxyFactory.create(
            model,
            props,
            model => view.update(model)
        );

        view.update(model);

        return proxy;
    }
}

ProxyFactory.js

class ProxyFactory {

    static create(objeto, props, acao) {
        return new Proxy(objeto, {

            get(target, prop, receiver) {
                if (props.includes(prop) && ProxyFactory._ehFuncao(target[prop])) {
                    return function () {
                        console.log(`interceptando ${prop}`);
                        Reflect.apply(target[prop], target, arguments);
                        return acao(target);
                    }

                }
                return Reflect.get(target, prop, receiver);
            },
            set(target, prop, value, receiver){

                if(props.includes(prop)){
                    acao(target);
                }
                return Reflect.set(target, prop, value, receiver);

            }
        });
    }

    static _ehFuncao(func){
        return typeof (func) == typeof(Function);
    }
}
10 respostas

Oi Vinícius tudo bem?

Poderia ver, por gentileza, também o código HTML e todos arquivos JS que ele chama e que você não postou ainda.

Olá, tudo ótimo. Sim, vou colocar aqui.

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Negociações</title>
    <link rel="stylesheet" href="css/bootstrap.css">
    <link rel="stylesheet" href="css/bootstrap-theme.css">

</head>
<body class="container">

    <h1 class="text-center">Negociações</h1>

    <div id="mensagemView"></div>

    <form class="form" onsubmit="negociacaoController.adiciona(event)">

        <div class="form-group">
            <label for="data">Data</label>
            <input type="date" id="data" class="form-control" required autofocus/>        
        </div>    

        <div class="form-group">
            <label for="quantidade">Quantidade</label>
            <input type="number" min="1" step="1" id="quantidade" class="form-control" value="1" required/>
        </div>

        <div class="form-group">
            <label for="valor">Valor</label>
            <input id="valor" type="number" class="form-control"  min="0.01" step="0.01" value="0.0" required />
        </div>

        <button class="btn btn-primary" type="submit">Incluir</button>
    </form>

    <div class="text-center">
        <button class="btn btn-primary text-center" type="button">
            Importar Negociações
        </button>
        <button onclick="negociacaoController.apaga()" class="btn btn-primary text-center" type="button">
            Apagar
        </button>
    </div> 
    <br>
    <br>
    <div id="negociacoesView"></div>
    <script src="js/app/models/Negociacao.js"></script>
    <script src="js/app/controllers/NegociacaoController.js"></script>
    <script src="js/app/helpers/DateHelper.js"></script>
    <script src="js/app/models/ListaNegociacoes.js"></script>
    <script src="js/app/views/View.js"></script>
    <script src="js/app/views/NegociacoesView.js"></script>
    <script src="js/app/models/Mensagem.js"></script>
    <script src="js/app/views/MensagemView.js"></script>
    <script src="js/app/services/ProxyFactory.js"></script>
    <script src="js/app/helpers/Bind.js"></script>
    <script>
        let negociacaoController = new NegociacaoController();
    </script>
</body>
</html>

Mensagem.js

class Mensagem{

    constructor(texto=''){

        this._texto = texto;
    }

    get texto(){

        return this._texto;
    }

    set texto(texto){

        this._texto = texto;
    }
}

MensagemView.js

class MensagemView extends View{

    constructor(elemento){
        super(elemento);
    }

    template(model){

        return model.texto ? `<p class="alert alert-info">${model.texto}</p>` : '<p></p>';
    }    

}

View.js

class View{

    constructor(elemento){

        this._elemento = elemento;
    }

    template(){
        throw new Error('O método template deve ser implementado');
    }

    update(model){
        this._elemento.innerHTML = this.template(model);
    }
}

Preciso também da Negociacao.js

DateHelper.js

NegociacoesView.js

Se achar que fica mais fácil pode subir todo projeto no github. Por experiência própria o erro pode estar em qualquer um desses arquivos que o HTML chama por isso quero ter tudo de uma vez para identificar o erro e corrigi-lo.

Certo, é só acessar o link. https://github.com/viniciuspinatti/javascript-oo2 Tudo está na pasta client.

Depois de definir a mensagem do texto que aparece

this._mensagem.texto = 'Negociação adicionada com sucesso';

você tem que colocar a linha logo abaixo

this._mensagemView.update(this._mensagem);

para poder atualizar a view.

Espero ter ajudado!!!

Mas André, no item 3 da aula 3, mais ou menos aos 10:38, se observar o código dele está funcionando, mas na linha que possui:

this._mensagem.texto = 'Negociação adicionada com sucesso';

Não possui o update na view embaixo. E mesmo assim funciona.

Hum, eu não sei o que aconteceu no vídeo.

Eu testei dessa forma com o seu código comparando com o projeto final e estava faltando update da view , coloquei e funcionou.

Não se apegue tanto a detalhes, o código é só para fins didáticos :) .

É que no exemplo justamente o instrutor estava demonstrando como tirar a responsabilidade do desenvolvedor de fazer update na view, realizando este automaticamente na alteração do atributo da mensagem. Gostaria que funcionasse pois o conceito me interessou.

solução!

Entendi, concordo contigo.

Abri o penúltimo projeto do professor e código estava lá. Debuguei o seu do momento que seta a mensagem de notificação. E debuguei o do professor também através do F12 do navegador.

Então achei a diferença:

No seu bind.js estava:

if(props.includes(prop)){
    acao(target);
 }
return Reflect.set(target, prop, value, receiver);

e no do professor estava

 let retorno = Reflect.set(target, prop, value, receiver);
 if(props.includes(prop)) acao(target);
 return retorno;

Fiz as mudanças e funcionou. Me parece que aqui define o update da view Reflect.set(target, prop, value, receiver); e depois chama de novo aqui para atualizar return retorno;

Muito obrigado André, agradeço toda a ajuda e atenção. Era exatamente o que eu precisava saber!