Search code examples
javascripterror-handlingprototyperesponse

Handling axios errors and responses (vue) works only with one error. How to notify multiple errors?


I have a Vue application which communicates with API (using axios requests) and return error(s). It works fine if I get only one error, for example when response is like this: {"error":"passwords.token"}

When i'm getting cumulated errors like this:

{"message":"The given data was invalid.",
 "errors":{
   "password":["The password confirmation does not match."]}
}

Here is my code of my Vue component and method resetPassword()

methods: {
        resetPassword () {
            this.$vs.loading()

            const payload = {
                userDetails: {
                    email: this.email,
                    password: this.password,
                    password_confirmation: this.password_confirmation,
                    token: this.token
                }
            }

            this.$store.dispatch('auth/resetPassword', payload)
                .then((response) => {
                    this.$vs.loading.close()
                    this.$vs.notify({
                        time: 10000,
                        title: 'Authentication Success',
                        text: response.message.data.message,
                        iconPack: 'feather',
                        icon: 'icon-success-circle',
                        color: 'success'
                    })
                })
                .catch(error => {
                    this.$vs.loading.close()
                    this.$vs.notify({
                        time: 6000,
                        title: 'Authentication Error',
                        text: error.message,
                        iconPack: 'feather',
                        icon: 'icon-alert-circle',
                        color: 'danger'
                    })
                })
        },
    },

Solution

  • I guess that the issue is that when you have more than one error, you only see one message The given data was invalid.

    Here is why:

    Whit this syntax:

    "errors":{
      "password":["The password confirmation does not match."]}
    }
    

    You are not using the error.message properly, as you use in the notify call:

    this.$vs.notify({
      time: 6000,
      title: 'Authentication Error',
      text: error.message,
      iconPack: 'feather',
      icon: 'icon-alert-circle',
      color: 'danger'
    })
    

    What you can do is return the same array of errors always, even if you have one error or ten errors:

    "errors": [
      {
        type: "password",
        message: "Wrong password"
      },
      {
        type: "user",
        message: "Wrong user"
      },
      // As recommendation, notify only "Authentication error", instead the specific field
      {
        type: "Authentication error",
        message: "Wrong credentials"
      },
    ]
    

    And you can notify this way:

    .catch(error => { // You return errors inside error object
      const errors = error.errors; // and you can get it here
      // const { errors } = error; // alternative syntax
      for (let err on errors) {
        this.$vs.notify({
          time: 6000,
          title: 'Authentication Error', // You can use err.type
          text: err.message,
          iconPack: 'feather',
          icon: 'icon-alert-circle',
          color: 'danger'
        })
      }
    }
    

    Alternative for:

    .catch(error => { // You return errors inside error object
      const errors = error.errors; // and you can get it here
      // const { errors } = error; // alternative syntax
      for (let i = 0; i < errors.length; i++) {
        this.$vs.notify({
          time: 6000,
          title: 'Authentication Error', // You can use errors[i].type
          text: errors[i].message,
          iconPack: 'feather',
          icon: 'icon-alert-circle',
          color: 'danger'
        })
      }
    }
    

    If you want to keep the structure in your error response, then check what kind of response are you getting and send the notification:

    .catch(err => { // You return errors inside error object
      const { error, errors } = err;
      if (error) { // only one error
        this.$vs.notify({
          time: 6000,
          title: 'Authentication Error',
          text: error.message,
          iconPack: 'feather',
          icon: 'icon-alert-circle',
          color: 'danger'
        })
      } else {
        for (let errorType of errors) { // more than one error
          this.$vs.notify({
            time: 6000,
            title: 'Authentication Error',
            text: errors[errorType][0],
            iconPack: 'feather',
            icon: 'icon-alert-circle',
            color: 'danger'
          })
        }
      }
    }
    

    It's not a good idea this approach, but if you want to use it, then it's fine.