Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue 3 + vuelidate@next: $v.$error remains false #707

Closed
jim-cooper opened this issue Sep 28, 2020 · 15 comments
Closed

Vue 3 + vuelidate@next: $v.$error remains false #707

jim-cooper opened this issue Sep 28, 2020 · 15 comments

Comments

@jim-cooper
Copy link

jim-cooper commented Sep 28, 2020

I'm using Vue 3 and Vuelidate@next and while $v.$invalid works $v.$error and $v.$dirty always remain false even though the individual validators show true (i.e. $v.password.$error returns true).

Sorry, couldn't figure out how to create a jsFiddle with vuelidate@next, but here is my relevant html and js:

  <input v-model.trim="$v.email.$model"/>
  <input v-model.trim="$v.password.$model"/>

  data() {
    return {
      email: '',
      password: '',
    };
  },
  validations: {
    email: { required },
    password: { required },
  },

Here is my full vue component if needed:

<template>
<div>
  <h2 class="header">Sign In</h2>
  $v.$error: {{$v.$error}}<br/>
  $v.$invalid: {{$v.$invalid}}<br/>
  $v.$dirty: {{$v.$dirty}}<br/>
  $v.$anyError: {{$v.$anyError}}<br/>
  $v.$anyInvalid: {{$v.$anyError}}<br/>
  $v.$anyDirty: {{$v.$anyDirty}}<br/>
   $v.password.$error: {{ $v.password.$error }}<br/>
  <form @submit="signIn" autocomplete="off" novalidate>
    <div class="form-group" :class="{ 'error' : $v.email.$error }">
      <label for="email">Email:</label>
      <!-- <em v-if="$v.email.$error && $v.email.email.$invalid">Invalid Email</em> -->
      <em v-if="$v.email.$error && $v.email.required.$invalid">Required</em>
      <input v-model.trim="$v.email.$model"/>
    </div>
    <div class="form-group" :class="{ 'error' : $v.password.$error }">
      <label for="password">Password:</label>
      <em v-if="$v.password.$error">Required</em>
      <input v-model.trim="$v.password.$model"/>
    </div>
    <div class="form-group buttons" >
      <button type="button" @click="cancel()">Cancel</button>
      <button class="save" type="submit" :disabled="$v.$errors.length > 0">
        Sign In
      </button>
    </div>
  </form>
</div>
</template>

<script>
import { required } from '@vuelidate/validators';

export default {
  name: 'SignIn',
  data() {
    return {
      email: '',
      password: '',
    };
  },
  validations: {
    email: { required },
    password: { required },
  },
  methods: {
    signIn(credentials) {
      this.userRepository.signIn(credentials)
        .subscribe(
          null,
          (err) => { console.$error(err, 'Error'); },
          () => this.router.navigate(['/catalog']),
        );
    },
    cancel() {
      this.router.navigate(['/']);
    },
  },
};

</script>

<style scoped>
form {
  color: #336699;
  font-size:18px;
  padding:30px;
  width: 298px;
  margin: 0 auto;
}
input {
  display: block;
  font-size:18px;
  padding-left:10px;
  width: 275px;
}
button {
  font-size: 24px;
  color: #336699;
}
button:disabled {
  color: #999999;
}
.header {
  color: #336699;
  text-align:center;
  padding-top:20px;
  margin-top:0;
}
.form-group {
  margin: 10px;
}
.buttons {
  text-align: right;
  margin-right: 0px;
}
.save {
  background-color: #CCDDFF;
  border-color: #CCDDFF;
}
em {float:right; color:#E05C65; padding-left:10px;}
.$error input, .$error select, .$error textarea {background-color:#E3C3C5;}
.$error ::-webkit-input-placeholder { color: #999; }
.$error :-moz-placeholder { color: #999; }
.$error ::-moz-placeholder { color: #999; }
.$error :ms-input-placeholder  { color: #999; }
</style>


@shentao
Copy link
Member

shentao commented Sep 28, 2020

Thanks for reporting! This looks like a bug in collecting the statuses among nested trees.
In the meantime, I think you can use the $errors array as a way to see if there are errors in the form.

@jim-cooper
Copy link
Author

Related to this, if I'm understanding the docs right, I think the following are also bugs with this version:

  • $v.$anyError is missing
  • $v.$anyInvalid is missing
  • $v.$invalid is false if there is an invalid field that is not dirty

@shentao
Copy link
Member

shentao commented Sep 28, 2020

The $invalid part is a bit tricky with the new version as now all the validators are lazy, meaning they won’t evaluate if the field is not $dirty. That means $invalid and $error are literally the same. Not sure if that’s the right direction to go though.

@MauroB45
Copy link

MauroB45 commented Oct 2, 2020

For me, the $invalid property being lazy by default is a big change. In my case, I am using the $invalid prior to any user interaction to control the state of a form "section" to remain in edit/display mode. If the section validation branch was invalid I would not close (set as display mode) the specific section. If valid It could be closed automatically and if $anyError was true then I would display error feedback to the user. I could manage this by keeping track of interactions or initial validations myself, but it was nice to be able to check the $invalid state for this.

If $invalid will be evaluated if the field is $dirty then is it any different of $error? I might be missing something.

@aethr
Copy link
Contributor

aethr commented Oct 2, 2020

Following on from what @MauroB45 has said, I agree that $invalid only being evaluated when $dirty is true is a big change, and it makes it hard to do some things that the previous implementation made very easy.

For example, many of our forms will have the Submit button disabled while any form field is $invalid. We display a red outline on form fields that have $error = true, but not on form fields that have $invalid = true. That way a form can be $invalid on load, disabling the submit button, but the user will only see a red outline on fields they've interacted with. This gives the user the opportunity to attempt filling out the entire form, and they only get negative feedback after they've interacted with a form field, but left it in an invalid state.

I don't disagree with evaluation being lazy, but perhaps there should be an option to trigger evaluation when validation is first set up, that doesn't mark fields as $dirty. Alternatively, perhaps giving an option to trigger validation manually without marking the validation dirty would also suffice?

@shentao
Copy link
Member

shentao commented Oct 2, 2020

Yup! This is something I've been thinking about. Having the validators lazy by default is pretty cool, but it definitely needs a way to be evaluated without being dirty. @dobromir-hristov whats your take here?
I will probably work on that during the weekend.

Might also reverse it somewhat so that initial evaluation is the default behavior and the user is able to make it lazy through config. @aethr

@dobromir-hristov
Copy link
Contributor

I have a Todo in the src we should fix this hehe

@aethr
Copy link
Contributor

aethr commented Oct 2, 2020

Might also reverse it somewhat so that initial evaluation is the default behavior and the user is able to make it lazy through config.

This sounds ideal to me. Lazy evaluation could be a bit of a foot-gun if developers don't understand what it means for $invalid and $dirty. Forcing users to opt-in means they'll get the least surprise, validation will work out of the box and if they want lazy evaluation they can read about it and turn it on after the understand the consequences.

@MasihTak
Copy link

MasihTak commented Dec 2, 2020

@shentao any update?

@Gyurmatag
Copy link

Gyurmatag commented Dec 8, 2020

Any update on this? My form has requeired fields but is $invalid="false" initially. This is not good.

@shentao
Copy link
Member

shentao commented Dec 9, 2020

Not yet :(

@michaelsaprykin
Copy link

I have faced the similar issue and it seems to be related

Here is my example:
While user is typing - if input field is valid ( there are some custom validations ) - I'm making an API call to receive some metadata that is connected to the value and then filling another block in the UI

On the next branch:
While I'm typing - $dirty, $invalid, $error - are false, and $errors is an empty array.
However, once I blur the field - $dirty becomes true and validations run.

It works okey on master branch

@dobromir-hristov
Copy link
Contributor

Should be fixed in latest version.

@bhaidar
Copy link

bhaidar commented Feb 13, 2022

@dobromir-hristov Is this fixed for vue2 v.0.7.7? I believe it's still failing for some reason. I appreciate your feedback. Thanks

@dobromir-hristov
Copy link
Contributor

@bhaidar - 0.7.7 was not touched, it should work as it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants