[Vuejs]-Add validation rule in yup based on external condition

0👍

To achieve what you want, you need to use when and pass a ConditionBuilder as the parameter and the builder accepts 2 parameters an empty array (which means an external dependency) and the schema of the current field.
make sure you have the latest version of yup installed. the version used in this example "yup": "^1.2.0"

example:

const rules = yup.object().shape({
  signedAt: yup.string().required('field is required'),
  startsAt: yup.string().required('field is required'),
  endsAt: yup.string().required('field is required'),
  acceptancePlaces: yup.array(yup.string()).when(([], schema) => {
  //your condition here
    if (condition) {
      return schema.min(1).required();
    }

    return schema.notRequired();
  }),
});

and here is a complete working code:

RulesComp.vue:

<script setup lang="ts">
import * as yup from "yup";
import {ref} from "vue";

const {documentSet} = defineProps<{
  documentSet: {
    regime: boolean
  }
}>()
const errorMessage = ref('');

const rules = yup.object().shape({
  signedAt: yup.string().required('field is required'),
  startsAt: yup.string().required('field is required'),
  endsAt: yup.string().required('field is required'),
  acceptancePlaces: yup.array(yup.string()).when(([], schema) => {
    if (documentSet.regime) {
      return schema.min(1).required();
    }

    return schema.notRequired();
  }),
});

const validateRules = async () => {
  await rules.validate({
    signedAt: 'signedAt',
    startsAt: 'startsAt',
    endsAt: 'endsAt',
  }).then(() => {
    errorMessage.value = '';
  }).catch((e) => {
    errorMessage.value = e.message;
  });
};
</script>

<template>
  <div :style="{
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: '20px',
  }">
    <button type="button" @click="validateRules()">validate</button>
    <p v-if="errorMessage">
      {{ errorMessage }}
    </p>
  </div>
</template>

App.vue:

<script setup lang="ts">
import RulesComp from './components/RulesComp.vue'
import {reactive} from "vue";

const documentSet = reactive({
  regime: false,
});
const toggleRegime = () => {
  documentSet.regime = !documentSet.regime;
};
</script>

<template>
  <RulesComp :documentSet="documentSet"/>
  <button @click="toggleRegime()">
    toggle Regime
  </button>
  <p>
    {{JSON.stringify(documentSet)}}
  </p>
</template>

enter image description here

Leave a comment