Comments (9)
PR merged, issue fixed
from vuelidate.
Hi!
I think you confused a few things, as arrays are a bit trickier in vue in general.
First of all, here is an example of a validation setup that should work for you if all other goes right.
validations: {
values: {
required, // array cannot be left empty
minLength: minLength(6) // "values" array has to have at least 6 elements
$each: {
minLength: minLength(4) // each field of "values" array has to have at least 4 characters (or be an array of at least 4 elements)
}
}
}
$each
is simply applied per array field, no matter if it's an object or not.
What you might have hit instead is forgetting to deal with arrays properly. Remember that setting a value in array requires usage of .set
method, so vue can notice the change and notify all dependants.
Here is a modified version of ExampleEachArray.vue
from the Collection validation section in the docs. I've used strings instead of objects inside the array. Notice that i cannot use v-model
any longer, I had to split it to :value
and @input
to use $set
properly.
<template lang="pug">
div
div(v-for="(person, index) in people")
.form-group(v-bind:class="{ 'form-group--error': $v.people.$each[index].$error }")
label.form__label Name for {{ index }}
input.form__input(:value="person" @input="$set(people, index, $event.target.value), $v.people.$each[index].$touch()")
span.form-group__message(v-if="!$v.people.$each[index].required") Name is required.
div
button.button(@click="people.push('')") Add
button.button(@click="people.pop()") Remove
.form-group(v-bind:class="{ 'form-group--error': $v.people.$error }")
span.form-group__message(v-if="!$v.people.minLength") List must have at least 2 elements.
span.form-group__message(v-else-if="!$v.people.required") List must not be empty.
span.form-group__message(v-else-if="$v.people.$error") List is invalid.
button.button(@click="$v.people.$touch") $touch
button.button(@click="$v.people.$reset") $reset
pre
| people: {{ people }}
| $v.people: {{ $v.people }}
</template>
<script>
import { required, minLength } from 'vuelidate/lib/validators'
export default {
data () {
return {
people: [
'John',
''
]
}
},
validations: {
people: {
required,
minLength: minLength(2),
$each: {
required
}
}
}
}
</script>
from vuelidate.
Thanks for quick answer !
Sorry I use :value
and @input
in my real code not v-model
. And I use Vue2 (so I've replaced .set()
by.splice()
)
But this doesn't work :
<template>
<div>
<div v-for="(person, index) in people">
<input type="text" :value="person" @input="people.splice(index, 1, $event.target.value), $v.people.$each[index].$touch()"/>
</div>
</div>
</template>
<script>
import { validationMixin } from 'vuelidate';
import { required, minLength } from 'vuelidate/lib/validators'
export default {
mixins: [validationMixin],
data () {
return {
people: [
'John',
''
]
}
},
validations: {
people: {
required,
minLength: minLength(2),
$each: {
required
}
}
},
}
</script>
If I fill second input, $invalid
remain to true
from vuelidate.
I screwed up. It indeed doesn't work now. I had to test it wrong, will update the code soon.
Btw, correct way of using $set
in Vue 2 is of course that $set(people, index, $event.target.value)
.
from vuelidate.
Ok, turned out this is a bug. Vue doesn't track access to array's properties in it's dependency tracking mechanism, so validators directly on array values are never updated after the initial run.
Anyway, the code from my first response (now correctly using $set
) should work if the bug was not present. No need for extra notation. I'll fix it soon.
from vuelidate.
Hey @Frizi any progress? Or a guidance on a PR?
from vuelidate.
Hi,
I had quite a busy time now, but I did tried to fix it. The problem really is that it's kinda broken in the framework, as arrays are treated differently than objects - their properties are not observable directly. The basic concept (what i tried already) would be to add dependency to the array directly, but it then forces recomputation of every $each
validator on every array modification. It breaks async validators.
Second i tried to limit the evaluation to only when the corresponding value in array has changed, but again it's problematic when you have external data dependencies on your model. Basically the validator is now not recomputed when they change.
Next step is to poke around validator gathering on array update, which is here:
https://github.com/monterail/vuelidate/blob/master/src/index.js#L227 I'd like to do it soon, but my time is limited now.
Another problem is the stability. Vue team is currently working on Proxy based notifications, which could solve this problem efficiently, but only for Proxy supporting browsers. Because of that, it's very discouraged to use private notification API, as it's very likely to change soon.
from vuelidate.
So, let's wait for good news, thank you @Frizi.
from vuelidate.
Just implemented and tested the solution, though it's using some (reasonably stable) private Vue APIs. Please check if it solves your problem.
from vuelidate.
Related Issues (20)
- ValidateEach support template refs
- ValidateEach and dynamic minValue HOT 1
- $validationGroups: there's not a way to group errors from nested forms.
- useVuelidate doesn't signal that it unwraps the validation ref when used in a template HOT 2
- sameAs doesn't work HOT 10
- Support ref (and possibly computed) HOT 2
- Not supporting this package in latest vue3 with typescript HOT 3
- InternalError: too much recursion: access validation states from a validation HOT 1
- How does i18n work when validators are chained?
- Validation inconsistent on Mobile Devices HOT 2
- Support Vue 3.x HOT 1
- a way to programatically set form/$model value without triggering validators
- root instance does not capture nested instances validations results if they have `$rewardEarly: true` and root does not.
- Getting path of validation error when validation fails in child component
- nuxt 3, $each helper does not work?
- $externalResults are not automatically cleared on $model change when using dynamic/computed rules HOT 1
- lazy validation option doesn't work HOT 1
- useVuelidate doesnt work in options API
- $rewardEarly stops working if a previous field is invalid HOT 1
- Vuelidate - foreach helper validation does not include $dirty property
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from vuelidate.