GithubHelp home page GithubHelp logo

Comments (9)

Frizi avatar Frizi commented on May 22, 2024 5

PR merged, issue fixed

from vuelidate.

Frizi avatar Frizi commented on May 22, 2024 1

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.

yabab-dev avatar yabab-dev commented on May 22, 2024

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.

Frizi avatar Frizi commented on May 22, 2024

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.

Frizi avatar Frizi commented on May 22, 2024

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.

jonataswalker avatar jonataswalker commented on May 22, 2024

Hey @Frizi any progress? Or a guidance on a PR?

from vuelidate.

Frizi avatar Frizi commented on May 22, 2024

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.

jonataswalker avatar jonataswalker commented on May 22, 2024

So, let's wait for good news, thank you @Frizi.

from vuelidate.

Frizi avatar Frizi commented on May 22, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.