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

Validação com Vue.js não está funcionando

Recebo o erro abaixo (modo dev no firefox) quando simulo uma requisição sem preencher o valor e a data de entrega da oferta:

Uncaught (in promise) TypeError: error.response.data.errors is undefined
    enviarOferta http://localhost:8080/oferta:149
    promise callback*enviarOferta http://localhost:8080/oferta:148
    VueJS 35
    mounted http://localhost:8080/oferta:130
    promise callback*mounted http://localhost:8080/oferta:122
    VueJS 7
    onLoad http://localhost:8080/oferta:113
    onload http://localhost:8080/oferta:1
oferta:149:12
    enviarOferta http://localhost:8080/oferta:149
    (Async: promise callback)
    enviarOferta http://localhost:8080/oferta:148
    enviarOferta self-hosted:1161
    VueJS 35
    mounted http://localhost:8080/oferta:130
    (Async: promise callback)
    mounted http://localhost:8080/oferta:122
    VueJS 7
    onLoad http://localhost:8080/oferta:113
    onload http://localhost:8080/oferta:1
3 respostas

Segue o fonte do arquivo home.html de ofertas:

<!DOCTYPE html>
<html>
<head th:replace="~{base :: head('Loja de ferramentas')}"></head>
<body onLoad="onLoad()">

    <div th:replace="~{base :: logo}"></div>
    <div id="ofertas" class="container">

        <div th:replace="~{base :: titulo('Faça uma oferta')}"></div>

        <div class="card mb-2" v-for="pedido in pedidos">

            <div class="card-header dark">{{pedido.nomeProduto}}</div>
            <div class="card-body">

                <div class="row">
                    <div class="col-12 col-sm-8">
                        <div>Produto</div>
                        <div>
                            <a v-bind:href="pedido.urlProduto">{{pedido.nomeProduto}}</a>
                        </div>
                        <div class="row">

                            <div class="col-md-4">
                                Valor:<input v-bind:class="{'is-invalid':pedido.erros.valor !== ''}" class="form-control" v-model="pedido.valorNegociado" />

                                <div class="invalid-feedback" v-if="pedido.erros.valor">
                                    {{pedido.erros.valor}}
                                </div>
                            </div>

                            <div class="col-md-8">
                                Data da entrega:<input v-bind:class="{'is-invalid':pedido.erros.dataEntrega !== ''}" class="form-control" v-model="pedido.dataEntrega" />

                                <div v-if="pedido.erros.dataEntrega" class="invalid-feedback">
                                    {{pedido.erros.dataEntrega}}
                                </div>
                            </div>
                        </div>
                        <div>
                            <label>Descrição</label>
                            <textarea disabled="disabled" class="form-control">{{pedido.descricao}}</textarea>
                        </div>
                        <div class="mt-2">
                            <label>Comentário</label>
                            <textarea class="form-control" v-model="pedido.comentario"></textarea>
                        </div>

                        <button v-if="pedido.ofertaEnviada" disabled="disabled" class="btn btn-success mt-2">Oferta enviada!</button>
                        <button v-else class="btn btn-primary mt-2" v-on:click="enviarOferta(pedido)">Enviar oferta</button>

                    </div>

                    <div class="col-12 col-sm-4">
                        <div>
                            <img class="img-thumbnail" v-bind:src="pedido.urlImagem" />
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script type="text/javascript">
    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: '',
                                  dataEntrega: ''
                              }
                          })
                         this.pedidos = response.data
                    })
            },
            methods: {
                enviarOferta: function(pedido) {
                    pedido.erros = {
                          valor: '',
                          dataEntrega: ''
                      };

                    axios
                      .post('http://localhost:8080/api/ofertas', {
                          pedidoId: pedido.id,
                          valor: pedido.valorNegociado,
                          dataEntrega: pedido.dataEntrega,
                          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>
solução!

Pela mensagem de erro você recebeu um callback em .catch(error porém nesse retorno não existe o campo "error.response.data.errors"

trecho de código com problema:

                      .catch(error => {
                          error.response.data.errors.forEach(error => {
                              pedido.erros[error.field] = error.defaultMessage;
                              })

Eu tinha comentado as validações nos atributos do DTO de ofertas. Tirei o comentário e voltou a funcionar.

Grato!