Reputation: 330
I can not make custom checkbox component with vee-validate support. I'm newbie in Vue. In my app checkbox must be required. But it doesn't work. I read a lot of articles about vee-validate and custom inputs, but all examples based on simple custom text inputs.
Below my code at this moment.
Parent component:
<!-- Custom text input. Vee-validate works nice. -->
<input-text
name="email"
placeholder="Please, enter email"
label="Email"
:required="true"
:type="'email'"
:value.sync="shareholder.fields.email"
v-validate.initial="'required|email'"
data-vv-delay="500"
:className="{'error': isShowError('email')}"
:disabled="isDisabled"
/>
<!-- Custom checkbox input. Vee-validate doesn't work. -->
<checkbox2
name="consent"
v-if="consent"
class="consent"
:required="true"
:disabled="isDisabled"
:className="{'error': errors.first('consent')}"
:error="errors.first('consent')"
v-model="consentStatus"
v-validate.initial="'required'"
>
{{consent.text}}<br><a :href="consent.link" target="_blank">{{consent.linkText}}</a>
</checkbox2>
{{ errors.first('consent') }}
File check-box.vue:
<template>
<div class="checkbox"
:class="{ active: !!value }"
>
<label class="control">
<input
@change="handleChange"
type="checkbox"
:name="name"
:checked="value"
/>
<span class="icon-checkbox"></span>
</label>
<div class="label">
<slot />
</div>
</div>
</template>
<script src="./check-box.js"></script>
<style lang="stylus" src="./check-box.styl" scoped></style>
File check-box.js:
export default {
name: 'checkbox2',
inject: [ '$validator', ],
// In one of articles I read I must bind event and value
// with check box like below. But it seems it doesn't work too.
model: {
event: 'input',
value: 'checked',
},
props: {
value: {
type: Boolean,
default: false,
},
error: {
type: String,
},
name: String,
disabled: Boolean,
className: Object,
required: Boolean,
},
data: function() {
return {
checked: false,
}
},
methods: {
handleChange() {
if (!this.disabled) {
this.checked = !this.value
// If I emit 'change' instead of 'input',
// checkbox component works wrong.
this.$emit('input', this.checked)
}
},
},
created() {
this.checked = this.value
this.$validator = this.$parent.$validator
},
}
Upvotes: 0
Views: 10643
Reputation: 330
User must check our check-box for making form valid.
At first, in vee-validate 'required'
for Boolean
is true
when it isn't equal null
. I.e. if consentStatus = null
, then checkbox below by default is not valid (as I need).
<checkbox2
name="consent"
v-if="consent"
class="consent"
:required="true"
:disabled="isDisabled"
:className="{'error': errors.first('consent')}"
:error="errors.first('consent')"
v-model="consentStatus"
v-validate.initial="'required'"
>
{{consent.text}}<br><a :href="consent.link" target="_blank">{{consent.linkText}}</a>
</checkbox2>
But in this case both possible values (true
and false
) make this component valid.
By default rule v-validate.initial="{ is: true }"
doesn't work for vee-validate 2.1.0-beta-9 and below. So we need a crutch.
In parent component js-file after imports we should define custom validator rule.
import { Validator } from 'vee-validate';
Validator.extend('isEqual', {
getMessage: field => 'Your text in case of checkbox mistake. ' + field + ' is invalid.',
validate: value => value
});
Code for parent vue file:
<checkbox2
name="consent"
v-if="consent"
class="consent"
:required="true"
:disabled="isDisabled"
:className="{'error': errors.first('consent')}"
:error="errors.first('consent')"
v-model="consentStatus"
v-validate.initial="{ isEqual: true }" // Here is difference!
>
{{consent.text}}<br><a :href="consent.link" target="_blank">{{consent.linkText}}</a>
</checkbox2>
{{ errors.first('consent') }}
We will compare values as numbers. Parent vue code:
<checkbox2
name="consent"
v-if="consent"
class="consent"
:required="true"
:disabled="isDisabled"
:className="{'error': errors.first('consent')}"
:error="errors.first('consent')"
v-model="consentStatus"
v-validate.initial="{ is: 1 }" // Here is difference!
>
{{consent.text}}<br><a :href="consent.link" target="_blank">{{consent.linkText}}</a>
</checkbox2>
{{ errors.first('consent') }}
File check-box.vue:
<template>
<div class="checkbox"
:class="{ active: !!value, error: !!error }"
>
<label class="control">
<input
@change="handleChange"
type="checkbox"
:name="name"
:checked="value"
/>
<span class="icon-checkbox"></span>
</label>
<div class="label">
<slot />
</div>
</div>
</template>
<script src="./check-box.js"></script>
<style lang="stylus" src="./check-box.styl" scoped></style>
File check-box.js:
export default {
name: 'checkbox2',
props: {
error: {
type: String,
},
value: Boolean,
name: String,
disabled: Boolean,
className: Object,
required: Boolean
},
methods: {
handleChange() {
if (!this.disabled) {
this.$emit('input', this.value ? 0 : 1);
}
}
}
}
Upvotes: 1