Я пытаюсь реализовать VeeValidate, чтобы проверить, установлен ли хотя бы один флажок
Я нашел пример jsfiddle, который я раздвоил, а затем отредактировал. Я не понимаю, что происходит или как это исправить. В моем примере я использую флажки со значениями, но когда я нажимаю флажок, значение изменяется на true или false в зависимости от того, установлен ли флажок.
const Checkboxes = {
template: '#checkboxTmpl',
data() {
return {
text: '',
options: [
{
name: 'Web',
slug: 'web'
},
{
name: 'iOS',
slug: 'ios'
},
{
name: 'Android',
slug: 'android'
}
]
};
},
created() {
this.$validator.extend('oneChecked', {
getMessage: field => 'At least one ' + field + ' needs to be checked.',
validate: (value, [testProp]) => {
const options = this.options;
// console.log('questions', value, testProp, options.some((option) => option[testProp]));
return value || options.some((option) => option[testProp]);
}
});
},
methods: {
validateBeforeSubmit(e) {
this.$validator.validateAll(); // why is oneChecked not validated here? --> manually trigger validate below
this.options.forEach((option) => {
this.$validator.validate('platforms', option.slug, ['checked'])
});
console.log('validator', this.errors);
if (!this.errors.any()) {
alert('succesfully submitted!');
}
}
}
};
Vue.use(VeeValidate);
const app = new Vue({
el: '#app',
render: (h) => h(Checkboxes)
})
<script src="https://cdn.jsdelivr.net/vee-validate/2.0.0-beta.18/vee-validate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>
<div id="app">
</div>
<script id="checkboxTmpl" type="text/template">
<form @submit.prevent="validateBeforeSubmit">
<label v-for="(option, index) in options">
<input type="checkbox"
v-model="option.slug"
name="platform"
v-validate.initial="option.slug"
data-vv-rules="oneChecked:checked"
data-vv-as="platform"/> {{option.name}}
</label>
<p v-show="errors.has('platform')">{{ errors.first('platform') }}</p>
<pre>{{options}}</pre>
<button type="submit">Submit</button>
</form>
</script>
Я не понимаю, почему все флажки установлены, и снятие отметки с одного из них возвращает ошибку проверки, хотя два все еще проверены. Мне нравится, что ошибки отображаются перед отправкой формы, но снятие отметки со всех и последующая отправка не вызывает ошибку проверки.
Я использую VeeValidate, потому что это то, что используется в примере, но любое другое решение будет хорошо. Я не хочу использовать jQuery в своем приложении vue.js.
Мне бы очень хотелось понять, что происходит.
1 ответ
Там было две основные проблемы:
- С помощью
v-model
на неправильном ключе. Фактически, каждый раз, когда флажок был отмечен или снят, он будет генерировать событие ввода, которое изменит исходный фрагмент параметра (в вашемdata
). Вместо этого вам нужно добавитьchecked
поле в вашем варианте. Затем в вашем шаблоне добавьте:checked
приписать и изменить вашv-model
быть:option.checked
, - Как сказано в документах VeeValidate, вы можете просто использовать
required
правило, чтобы убедиться, что флажок должен быть установлен для отправки вашей формы. Вот ссылка на документы. Поэтому вам не нужны вашиcreated
блок.
Кроме того, validateAll
Функция возвращает обещание, содержащее результат проверки. Так что не нужно использовать this.errors.any()
тоже.
Кроме того, я обновил библиотеку VeeValidate до последней версии, поскольку вы использовали бета-версию.
Вот рабочий код:
const Checkboxes = {
template: '#checkboxTmpl',
data() {
return {
text: '',
options: [{
name: 'Web',
slug: 'web',
checked: false
},
{
name: 'iOS',
slug: 'ios',
checked: true
},
{
name: 'Android',
slug: 'android',
checked: true
}
]
};
},
methods: {
validateBeforeSubmit(e) {
this.$validator.validateAll().then(value => {
if (value) {
alert('successfully submitted')
}
})
}
}
};
Vue.use(VeeValidate);
const app = new Vue({
el: '#app',
render: (h) => h(Checkboxes)
})
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.js"></script>
<script src="https://unpkg.com/vee-validate@latest"></script>
<script id="checkboxTmpl" type="text/template">
<form @submit.prevent="validateBeforeSubmit">
<label v-for="(option, index) in options">
<input type="checkbox"
:checked="option.checked"
v-model="option.checked"
name="platform"
v-validate="'required'"/> {{option.name}}
</label>
<p v-show="errors.has('platform')">{{ errors.first('platform') }}</p>
<pre>{{options}}</pre>
<button type="submit">Submit</button>
</form>
</script>
Надеюсь, это поможет!