VeeValidate server side validations
Tags: vue, veevalidate, asyncawait, javascript
Published: 2020-02-02 10:43:34

---
title: VeeValidate server side validations
published: true
description: A simple example of an asynchronous VeeValidate rule.
tags: vue, vee-validate, async/await, javascript
---

In this post we'll look at how to add a [VeeValidate](https://logaretm.github.io/vee-validate/overview.html) rule for validating a value with an API endpoint. A scenario where such a rule is useful could be checking if a username is unique.

Rather than displaying an error after the form is submitted, we'd like to inform the user right away that their username is already taken.

We'll start with this simple component using a `ValidationObserver` and `ValidationProvider`.

```vue
<template>
  <ValidationObserver v-slot="{ invalid }">
    <ValidationProvider name="username" rules="required" v-slot="{ errors }">
      <p>
        <input placeholder="username" v-model="username" type="text">
        <br>
        <span id="error">{{ errors[0] }}</span>
      </p>
    </ValidationProvider>
    <button @click="sendForm" :disabled="invalid" type="button">Submit</button>
  </ValidationObserver>
</template>

<script>
import { ValidationProvider, ValidationObserver, extend } from "vee-validate";
import { required } from "vee-validate/dist/rules";

extend("required", {
  ...required
});

export default {
  data: function() {
    return {
      username: null
    };
  },
  components: {
    ValidationProvider,
    ValidationObserver
  },
  methods: {
    sendForm() {
      alert(`Thanks ${this.username}`)
    }
  }
};
</script>
```

Let's add the method that calls our API. For this example I'll use the Github API to look up usernames. The endpoint URI is `https://api.github.com/users/:username`. 

Github returns a 404 when the username is not found, in our case that means the field is valid. Whatever your situation is, this method should return `true` if valid and `false` if not.

```js
export default {
  // ...
  methods: {
    async isUsernameUnique() {
      try {
        const response = await axios.get(
          `https://api.github.com/users/${this.username}`
        );
        return false;
      } catch (err) {
        if (err.response.status === 404) {
          return true;
        }
      }
    }
  }
  // ...
}
```

Now that we have the method in place we can tell VeeValidate to use it in our new rule.

```js
export default {
  // ...
  mounted() {
    extend("unique", {
      validate: this.isUsernameUnique,
      message: "Username already taken"
    });
  }
  // ...
}
```

Lastly, we add the rule to the `ValidationProvider`.

```html
    <ValidationProvider name="username" rules="required|unique" :debounce="500" v-slot="{ errors }">
      <p>
        <input placeholder="username" v-model="username" type="text">
        <br>
        <span id="error">{{ errors[0] }}</span>
      </p>
    </ValidationProvider>
```

Note that I've added a `:debounce` attribute. This ensures we won't be overflowing the API with requests at every keypress but rather every 500ms.

You can find the entire source code for this example on CodeSandbox.

[![Edit vee-validate-api-validation-example](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/fervent-moon-yoi2s?fontsize=14&hidenavigation=1&theme=dark)

## Using `handleSubmit`

To prevent the user from sending the form before we have heard back from our API we can use `handleSubmit`. It takes our own `sendForm` method as an argument and using it is very straightforward.

```html
  <ValidationObserver v-slot="{ invalid, handleSubmit }">
    <!-- the rest of our form -->
    <button @click="handleSubmit(sendForm)" :disabled="invalid" type="button">Submit</button>
  </ValidationObserver>
```

Hopefully this simple example will be useful for writing your own server side validation rules.