How to use Quasar ":rules" with the Yup schema builder?

Viewed 592

I am using Quasar to build my Vue app.

It comes with form validation baked in through the use of the :rules prop.

Example 1 (inline):

<q-input
  ref="inputRef"
  filled
  v-model="model"
  label="Required Field"
  :rules="[val => !!val || 'Field is required']"
/>

Example 2 (rule extracted to a varible):

<template>
  <q-input
    ref="inputRef"
    filled
    v-model="model"
    label="Required Field"
    :rules="emailRules"
  />
</template>

<script setup>
const emailRules = val => !!val || 'Field is required';
</script>

But instead of writing out my own rule schema (and possibly missing lots of edge cases) I want to use the popular Yup validation schema library.

So how do I combine Yup with these Quasar rules?

I was thinking I could do something like this:

<template>
  <q-input
    ref="inputRef"
    filled
    v-model="model"
    label="Required Field"
    :rules="emailRules"
  />
</template>

<script>
import * as yup from 'yup';
const emailSchema = yup.string().email();
const emailRules = [(val) => await emailSchema.isValid(val) || 'Access the Yup error message here somehow??' ];
</script>

But I don't know how to access the default error message returned by Yup and use it in the second half of the rule.

1 Answers

I've not heard of a way to use yup in the :rules prop so far, but you could work around that with basic reactivity and event handling. (This is untested as is but you should be able to get the idea).

<template>
  <q-input
    filled
    v-model="model"
    :error="valid === false"
    :error-message="errorMessage"  // Only shows if `:error` is `true`.
    @blur="handleValidate"
  />
</template>

<script setup>
import { ref } from 'vue';
import * as yup from 'yup';

// ...however you are handling the `model` data.

const valid = ref(null);
const errorMessage = ref(null);

const handleValidate = async (value) => {
  const emailSchema = yup.string().email().required();
  await emailSchema
    .validate(value)
    .then((validated) => {
      // Do whatever you want in here with the validated value, 
      // but at least set the reactive values appropriately.
      valid.value = true;
      errorMessage.value = null;
    })
    .catch((error) => {
      // You can transform the error however you want before
      // rendering it on the component.
      valid.value = false;
      errorMessage.value = error;
    })
};
</script>

That should get you most of the way towards yup-driven field validation.

If you start thinking like this though you may as well just go ahead and use vee-validate (which I like) or other similar libraries out there, which offer lots of nice abstractions for doing just this sort of schema validation, at both the field-level and at the form-level, which will lead you down calm and sane pathways.

Related