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

Uncaught (in promise) TypeError: Cannot read property 'forEach' of undefined

Ao clicar no botão "Enviar Oferta" é apresentado o seguinte erro no console do navegador: Uncaught (in promise) TypeError: Cannot read property 'forEach' of undefined

Copiei o html do projeto da aula achando que poderia ser algum erro no meu código mas mesmo assim o erro continua. Fiz várias pesquisas na web mas não consigo achar a causa.

home.html

<html>
<head th:replace="~{base::head}"></head>
<body onload="onLoad()">
    <div th:replace="~{base::logo}"></div>
    <div class="container" id="ofertas">
        <div th:replace="~{base::titulo('Ofertas')}"></div>
        <div class="card mb-3" v-for="pedido in pedidos">
            <div class="card-header alert-dark">{{pedido.nomeProduto}}</div>
            <div class="card-body">
                <div class="row">
                    <div class="col-12 col-sm-8 mb-3">
                        <div>Produto</div>
                        <div>
                            <a v-bind:href="pedido.urlProduto">{{pedido.nomeProduto}}</a>
                        </div>

                        <div class="mt-2">Descrição</div>
                        <div>
                            <textarea disabled="disabled" class="form-control">{{pedido.descricao}}</textarea>
                        </div>
                        <div class="row mt-3">
                            <div class="col-md-5">
                                Valor: <input
                                    v-bind:class="{'is-invalid':pedido.erros.valor!==''}"
                                    class="form-control" v-model="pedido.valorNegociado" />
                            </div>
                            <div v-if="pedido.erros.valor" class="invalid-feedback">{{pedido.erros.valor}}</div>
                            <div class="col-md-7">
                                Data de Entrega: <input
                                    v-bind:class="{'is-invalid':pedido.erros.dataDaEntrega!==''}"
                                    class="form-control" v-model="pedido.dataDaEntrega" />
                            </div>
                            <div v-if="pedido.erros.dataDaEntrega" class="invalid-feedback">{{pedido.erros.valor}}</div>
                        </div>
                        <div class="mt-2">
                            <label>Comentário</label>
                            <textarea class="form-control" v-model="pedido.comentario"></textarea>
                        </div>
                        <button v-if="pedido.ofertaEnviada" class="btn btn-success mt-2">Oferta
                            Enviada</button>
                        <button v-else v-on:click="enviarOferta(pedido)"
                            class="btn btn-primary mt-2">Enviar Oferta</button>
                    </div>
                    <div class="col-12 col-sm-4">
                        <div>
                            <img class="img-thumbnail" style="height: 250px"
                                v-bind:src="pedido.urlImagem" />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script>
        function onLoad() {
        var app = new Vue(
        {            
            el: '#ofertas',
            data: {
                pedidos: []
            },
            mounted() {
                axios
                      .get('http://localhost:8080/api/pedidos/aguardando')
                      .then(response => {
                          response.data.forEach(pedido => {
                              pedido.ofertaEnviada = false;
                              pedido.erros = {
                                  valor: '',
                                  dataDaEntrega: ''
                              }
                          })
                          this.pedidos = response.data                          
                      })
            },
            methods: {
                enviarOferta: function(pedido) {
                    axios
                          .post('http://localhost:8080/api/ofertas', {
                              pedidoId: pedido.id,
                              valor: pedido.valorNegociado,
                              dataDaEntrega: pedido.dataDaEntrega,
                              comentario: pedido.comentario
                          })
                          .then(response => pedido.ofertaEnviada = true)
                          .catch(error => {
                            error.response.data.errors.forEach(error => {
                                pedido.erros[error.field] = error.defaultMessage;
                            })
                          })
                    }
                }
            });
        }
    </script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</body>
</html>
3 respostas

O erro não parece estar nesse código.

  • Em OfertasRest.java você anotou criaOferta com @PostMapping?
  • Em WebSecurityConfig.java você está usando .csrf().disable() ?
  • Em model/Pedido.java você anotou private List<Oferta> ofertas; com @JsonIgnore ?
  • Você tá usando @JsonIgnore em model/Oferta.java?
  • Você tem um pedido de cada tipo no banco de dados?

O meu funcionou e está assim:

  • .csrf().disable()
  • @JsonIgnore em private List<Oferta> ofertas;
  • model/Oferta.java sem @JsonIgnore

Luiz, a resposta pra todas as perguntas é sim com exceção da penúltima, não estou usando @JsonIgnore em model/Oferta.java. Nessas questões está exatamente igual o seu porém apresenta esse erro, acredito que seja realmente algo relacionado ao Vue JS.

solução!

O problema eram as anotações @NotNull na classe RequisicaoNovaOferta, comi bola e acabei esquecendo de incluí-las. Depois disso executei a inclusão de novas ofertas sem problema.

package br.com.alura.mvc.mudi.dto;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import br.com.alura.mvc.mudi.model.Oferta;

public class RequisicaoNovaOferta {

    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    private Long pedidoId;

    @Pattern(regexp = "^\\d+(\\.\\d+{2})?$")
    @NotNull
    private String valor;

    @Pattern(regexp = "^\\d{2}/\\d{2}/\\d{4}$")
    @NotNull
    private String dataDaEntrega;

    private String comentario;

    public Long getPedidoId() {
        return pedidoId;
    }

    public void setPedidoId(Long pedidoId) {
        this.pedidoId = pedidoId;
    }

    public String getValor() {
        return valor;
    }

    public void setValor(String valor) {
        this.valor = valor;
    }

    public String getDataDaEntrega() {
        return dataDaEntrega;
    }

    public void setDataDaEntrega(String dataDaEntrega) {
        this.dataDaEntrega = dataDaEntrega;
    }

    public String getComentario() {
        return comentario;
    }

    public void setComentario(String comentario) {
        this.comentario = comentario;
    }

    public Oferta toOferta() {
        Oferta oferta = new Oferta();
        oferta.setComentario(this.comentario);
        oferta.setDataDaEntrega(LocalDate.parse(this.dataDaEntrega, formatter));
        oferta.setValor(new BigDecimal(this.valor));
        return oferta;
    }

}