logaretm / vee-validate

✅ Painless Vue forms
https://vee-validate.logaretm.com/v4
MIT License
10.82k stars 1.27k forks source link

Axios & Pages = Injection:true ? #1585

Closed edukmattos closed 6 years ago

edukmattos commented 6 years ago

Hi ! I'm new to the world of Vue. I'm using vuex and axios (api Laravel) in my application. I'm getting server-side errors and making them available in Vue through vee-validate. My difficulty is to add all the errors coming from Laravel's api at the same time in a vuex action (store / auth.js) and make them available on a vue page (Login.vue).

mainjs

Vue.use(VeeValidate, 
  { 
    inject: true, 
    fieldsBagName: 'formFields' 
  });

store/auth.js

import axios from 'axios';

export default {
  namespaced: true,

  state: {
    user: [],
    token: '',
    status: ''
  },

  actions: {
    actLogin ({ commit }, credentials) {
      return new Promise((resolve, reject) => {
        commit('mutAuthRequest');
        axios.post(process.env.API_BASE_URL + '/login', credentials)
          .then(response => { 
            let token = response.data.access_token.token;
            let user = response.data.user;
            commit('mutAuthSuccess', { token, user });
            resolve(response);
          })
          .catch(error => {
            if (error.response.status === 401) {
              this.errors = error.response.data;
              this.dispatch('errors/actErrorsAdd', this.errors, { root: true });
            }
            reject(error);
          });
      });
    },

    actLogout ({ commit }) {
      commit('mutLogout');
    },

    actRegister ({ commit }, credentials) {
      console.log('Credentials: ', credentials);
      return new Promise((resolve, reject) => {
        axios.post(process.env.API_BASE_URL + '/register', credentials)
          .then(response => { 
            this.$router.push('/verify');
            resolve(response);
          })
          .catch(error => {
            if (error.response.status === 401) {
              this.errors = error.response.data;
// ---------->  How do I add multiple errors at the same time?  <--------------
              console.log('errors: ', this.errors);
            }
            reject(error);
          });
      });
    }
  },

  mutations: {
    mutAuthRequest (state) {
      state.status = 'loading';
    },

    mutAuthSuccess (state, { token, user }) {
      localStorage.setItem('token', token);
      localStorage.setItem('user', JSON.stringify(user));
      state.token = token;
      state.user = user;
      state.status = 'success';
    },

    mutLogout (state) {
      state.status = '';
      state.token = '';
      state.user = [];
      localStorage.removeItem('token');
      localStorage.removeItem('user');
    }
  },

  getters: {
    getUserName: state => {
      return state.user.name;
    }
  }
};

pages/auth/Login.vue

<template>
  <v-app id="login" class="primary">
    <v-content>
      <v-container fluid fill-height>
        <v-layout align-center justify-center>
          <v-flex xs12 sm8 md4 lg4>
            erros: {{ errors.items.map(e => e.msg) }} 
            <v-card class="elevation-1 pa-3">
              <v-card-text>
                <div class="layout column align-center">
                  <img src="/static/m.png" alt="Vue Material Admin" width="120" height="120">
                  <h1 class="flex my-4 primary--text">SisCad</h1>
                </div>                
                <v-form>
                  <v-text-field 
                    prepend-icon="mail" 
                    id="email"
                    name="email" 
                    label="E-mail" 
                    type="text" 
                    v-model.trim="credentials.email"
                    :error="(errors.has(this.pageName + '.email') ? true : false)"
                    :hint="errors.first(this.pageName + '.email')"
                    :persistent-hint="(errors.first(this.pageName + '.email') ? true : false)"
                    :append-icon="(errors.first(this.pageName + '.email') ? 'warning' : '')">
                  </v-text-field>

                  <v-text-field 
                    prepend-icon="lock" 
                    id="password"
                    name="password" 
                    label="Senha"  
                    type="password" 
                    v-model.trim="credentials.password"
                    :error="(errors.has(this.pageName + '.password') ? true : false)"
                    :hint="errors.first(this.pageName + '.password')"
                    :persistent-hint="(errors.first(this.pageName + '.password') ? true : false)"
                    :append-icon="(errors.first(this.pageName + '.password') ? 'warning' : '')">
                  </v-text-field>
                </v-form>
              </v-card-text>
              <v-card-actions>
                <v-layout justify-space-between>
                  <router-link to="/foo">Esqueci a Senha</router-link>
                </v-layout>
                <v-layout justify-space-between>
                  <router-link to="/register">Nova Conta</router-link>
                </v-layout>
                <v-btn block color="primary" @click="onSubmit" :loading="loading">Entrar</v-btn>
              </v-card-actions>
            </v-card>
          </v-flex>
        </v-layout>
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
import VeeValidate from 'vee-validate';
export default {
  data: () => ({
    pageName: 'PageLogin',
    loading: false,
    credentials: {
      email: '',
      password: ''
    }
  }),

  mounted () {
    this.$store.dispatch('auth/actLogout');
  },

  methods: {
    onSubmit () {
      this.errors.clear(this.pageName); 
      this.$store.dispatch('auth/actLogin', this.credentials);

      /*
      this.addError();
      */     
    },

    addError () {
      this.errors.add({
        field: 'email',
        msg: 'Inválido',
        scope: this.pageName
      });
      /*
      this.errors.add({
        field: 'password',
        msg: 'Obrigatório',
        scope: this.pageName
      });
      */
    }
  }

};
</script>

<style scoped lang="css">
  #login {
    height: 50%;
    width: 100%;
    position: absolute;
    top: 0;
    left: 0;
    content: "";
    z-index: 0;
  }
</style>
logaretm commented 6 years ago

errors.add can accept an array of errors, so you can add a bunch of errors at the same time. Does that answer your question?

edukmattos commented 6 years ago

Could you give me an example?

actLogin ({commit}, credentials) { return new Promise ((resolve, reject) => { commit ('mutAuthRequest'); axios.post (process.env.API_BASE_URL + '/ login', credentials) .then (response => { let token = response.data.access_token.token; let user = response.data.user; commit ('mutAuthSuccess', {token, user}); resolve (response); }) .catch (error => { if (error.response.status === 401) { this.errors = error.response.data; // ----------> How do I add multiple errors at the same time? <-------------- } reject (error); }); }); },

logaretm commented 6 years ago

Assuming the errors returned contains a fieldName/errorMessage object you can do it like that:

const errors = error.response.data;

// convert an object of errors to an array.
const errorsArray = Object.keys(errors).reduce((arr, fieldName) => {
  arr.push({
   field: fieldName,
   msg: errors[fieldName],
   scope: this.pageName
  });
}, []);

// add them to the bag.
this.errors.add(errorsArray);
edukmattos commented 6 years ago

Great ! Its works ! Thank You !