javascriptvue.jsvuejs3vuelidate

Vuelidate: Only validate checkbox if property is true


I have a form that is used for logging in, and in some cases some of the users should also tick a checkbox when logging in in the same form.

In those cases I want to make sure that the user have actually checked the checkbox in the form. I have the following code in my vue component (have more as well like a password, but this is probably the relevant part):

<script setup lang="ts">
    import {ref, defineProps} from 'vue';
    import useVuelidate from '@vuelidate/core';
    import {required, sameAs, email as emailValidation, requiredIf, helpers} from '@vuelidate/validators';
    
    interface Props {
        showAcceptTermsBox: boolean;
    }
    
    const props = defineProps<Props>();
    
    const email = ref('');
    const acceptTerms = ref(false);
    
    const rules = computed(() => ({
        email: {
            required: helpers.withMessage('Please fill out e-mail', required),
            email: helpers.withMessage('Please fill out e-mail correctly', emailValidation)
        },
        acceptTerms: {
            required: helpers.withMessage('Please accept terms and conditions', requiredIf(() => props.showAcceptTermsBox)),
            sameAs: helpers.withMessage('Please accept terms and conditions', sameAs(true))
        }
    }));
    
    const v$ = useVuelidate(rules, {
        email,
        acceptTerms
    }, {
        $scope: false
    });
</script>

<template>
    <form>
        <label for="email">E-mail:</label>
        <input type="email" v-model="email" id="email" />
        <div v-if="showAcceptTermsBox">
            <input type="checkbox" v-model="acceptTerms" id="acceptterms" />
            <label for="acceptterms">Accept</label>
        </div>
        <button type="submit">Submit</button>
    </form>
</template>

The checkbox is correctly only shown if the property called showAcceptTermsBox is true otherwise it's not visible on the page. I only want the checkbox to be validated if it's visible, otherwise it should be ignored in the validation. But the problem is that the checkbox is validated nomatter if showAcceptTermsBox is true or false. So my question is if it's possible to use something similar to the requiredif when using the sameAs, that I need to use when validating a checkbox.

A note: The validation works as expected on other fields in the form, so check if it's a correct e-mail etc., so in general the validation is working as expected, only need the final part regarding the checkbox.

Any help would be highly appreaciated.

Thanks in advance.


Solution

  • It just needs one trick, here you go.

    import {
      computed,
    } from 'vue';
    
    const rules = computed(() => {
      let dynamicRules: any = {
        email: {
          required: helpers.withMessage(
            'Please fill out e-mail',
            required,
          ),
          email: helpers.withMessage(
            'Please fill out e-mail correctly',
            emailValidation,
          ),
        },
      }
      // Dynamically add check fields ✅
      if(props.showAcceptTermsBox) {
        dynamicRules = {
          ...dynamicRules,
          acceptTerms: {
            required: helpers.withMessage(
              'Please accept terms and conditions',
              requiredIf(() => props.showAcceptTermsBox),
            ),
            sameAs: helpers.withMessage(
              'Please accept terms and conditions',
              sameAs(true),
            ),
          }
        }
      }
      return dynamicRules;
    });