Vue JS - Checkbox validation error on submit

Viewed 2356

In my registration form I have checkbox that confirms whether the user accepted the terms and conditions. The checkbox should validate once I hit the submit button, however since the checkbox is initially unselected, the validation error shows up straight away. Eventually, the error disappears reactively once I tick the checkbox, but for this particular scenario I would like to have the validation error show up only after I hit submit (if I did not check it). I'm not getting any particular console errors, but I'm simply getting stuck on the execution. Would anyone be able to show me how I can achieve this? I'd appreciate any help!

Checkbox.vue - this is the component representing the checkbox.

<template>
  <div class="check-wrapper">
    <label :for="id" class="check-label">
      <input v-model="checkboxValue"
             :id="id"
             :checked="isCheckboxChecked"
             :oninput="checkCheckbox()"
             type="checkbox"
             name="newsletter"/>
      <span v-if="labelText && !isLabelHtmlText">{{ labelText }}</span>
      <span v-if="labelText && isLabelHtmlText" class="label-html" v-html="labelText"></span>
      <span :class="{'check-mark-error': checkboxError}" class="check-mark"></span>
    </label>
    <p v-if="checkboxError" class="checkbox-error text-error">{{checkboxError}}</p>
  </div>
</template>

<script>
  data: () => ({
    checkboxValue: false
  }),
  methods: {
    updateValue: function () {
      if (this.$props.callback) {
        this.$props.callback(this.$props.id, this.$props.checkboxData, this.checkboxValue);
      }
    },
    checkCheckbox: function () {
      this.updateValue();
    }
  }
</script>

Register.vue - this is the parent component where the registration takes place

<template>
   <BasicCheckbox :id="'terms-privacy'"
                  :callback="onTermsClick"
                  :label-text="'terms and conditions'"
                  :is-label-html-text="true"
                  :checkbox-error="termsPrivacyError"
                  class="terms-privacy"/>
</template>
<script>
  methods: {
    validateData: function (data) {
      if (!this.termsPrivacyError) {
        this.sendRegistration(data).then(response => {
          if (response) {
            console.log('Registration successful');
            this.loginUser({email: data.email, password: data.password}).then(response => {
              if (response) {
                console.log('User logged in!');
                this.$router.push({name: ROUTE_NAMES_HOME.HOME});
              }
            })
          }
        });
      }
    },

    // Terms and Privacy Checkbox
    onTermsClick: function (checkboxId, checkboxData, data) {
      this.termsPrivacyError = !data ? termsPrivacyErrorText : '';
    },
  }
</script>
2 Answers

First of all, this is not an elegant solution but it works, we use a computed value to control if the error should be displayed. We update it in submit method, and cancel it when we click it checkbox for demonstration purpose.

new Vue({
  el: "#app",
  data: {
    termsState: false,
    validated: false
  },
  computed: {
    termsError() {
      return this.validated && !this.termsState
    }
  },
  methods: {
    handleTermsState() {
      this.validated = false
    },

    handleSubmit() {
      this.validated = true
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
  <label for="terms">
            Terms and Privacy Policy
            <input type="checkbox" id="terms" name="terms" v-model="termsState"  @change="handleTermsState">
            {{ termsState }}
        </label>
  <p style="color: red" class="for-error terms-error" v-if="termsError">You have to agree the terms and privacy condition.</p>
  <div><button type="submit" @click="handleSubmit">Submit</button></div>
</div>

From your scenario, what I understood, the validation is not happening when the user didn't check privacy and policy. If the user ticks and unticks the checkbox, the validation is working.

If that's the case, what you can do is check the child component "Checkbox.vue" data property "checkboxValue" value, as the default value is already false, and it will be true if the user did the action and tick the checkbox. Just before submitting the form, add the checkboxValue condition check.

Here is the updated Register.vue component file:

<template>
  <BasicCheckbox
    :id="'terms-privacy'"
    :callback="onTermsClick"
    :label-text="'terms and conditions'"
    :is-label-html-text="true"
    ref="BasicCheckbox"
    :checkbox-error="termsPrivacyError"
    class="terms-privacy"
  />
</template>
<script>
methods: {
  validateData: function (data) {
    if (!this.termsPrivacyError && this.$refs.BasicCheckbox.checkboxValue) {
      this.sendRegistration(data).then(response => {
        if (response) {
          console.log('Registration successful');
          this.loginUser({email: data.email, password: data.password}).then(response => {
            if (response) {
              console.log('User logged in!');
              this.$router.push({name: ROUTE_NAMES_HOME.HOME});
            }
          })
        }
      });
    }
  },

  // Terms and Privacy Checkbox
  onTermsClick: function (checkboxId, checkboxData, data) {
    this.termsPrivacyError = !data ? termsPrivacyErrorText : '';
  },
}
</script>

What I modified only:

I added the attribute of ref for the component stage `BasicCheckbox':

ref="BasicCheckbox"

And for the validation, I just only added condition whether the ref component 'BasicCheckbox' has value `true':

if (!this.termsPrivacyError && this.$refs.BasicCheckbox.checkboxValue)
Related