logaretm / vee-validate

✅ Painless Vue forms
https://vee-validate.logaretm.com/v4
MIT License
10.74k stars 1.26k forks source link

A space is not placed when entering text (Vuetify + Vee-Validate) #4300

Open semivan opened 1 year ago

semivan commented 1 year ago

What happened?

Issue with v-model.trim when using vee-validate: unable to insert space at the end of text in because it is being forced to be trimmed on space button press event

<script setup lang="ts">
  import { useField, useForm } from 'vee-validate';

  const { handleSubmit } = useForm();
  const name = useField('name', undefined, { syncVModel: false });
  const { value: nameValue, errorMessage: nameError } = name;
  const onSubmit = handleSubmit(values => console.log(values));
</script>

<template>
  <v-form @submit="onSubmit">
    <v-text-field type="text" v-model.trim="nameValue" :error-messages="nameError" /> 
  </v-form>
</template>

Reproduction steps

Run https://github.com/semivan/vee-validate-test and enter the text with a space in the first v-text-field

Version

Vue.js 3.x and vee-validate 4.x

What browsers are you seeing the problem on?

Relevant log output

No response

Demo link

https://github.com/semivan/vee-validate-test

Code of Conduct

logaretm commented 1 year ago

This is a weird one, not sure why passing error messages causes this. Will look into it.

semivan commented 1 year ago

It seems like I've figured out what the problem is.

If you output nameError in the console using watchEffect, you can see that every time the name field changes, nameError gets updated, even if there are no errors. This is causing the v-model to update unnecessarily. The same issue occurs with the useForm().errors field.

watchEffect(() => console.log(nameError.value));

Снимок экрана от 2023-09-09 15-57-43

To solve this problem, you can wrap the useForm().errors field and update it only when there are changes in the object. Then everything should work correctly.

<script setup lang="ts">
import { ref, watchEffect } from 'vue';
import * as yup from 'yup';
import _ from 'lodash';
import { useField, useForm } from 'vee-validate';

const validationSchema = yup.object({
  name: yup.string().max(5),
});
const { handleSubmit, errors } = useForm({ validationSchema });
const name = useField('name', undefined, { syncVModel: false });
const { value: nameValue } = name;
const onSubmit = handleSubmit(values => console.log(values));

const errorsWrapper = ref<{ name?: string }>({});

watchEffect(() => {
  if (!_.isEqual(errors.value, errorsWrapper.value)) {
    errorsWrapper.value = errors.value;
  }
});
</script>

<template>
  <v-form @submit="onSubmit">
    <v-text-field
      type="text"
      label="Uses an errors wrapper"
      v-model.trim="nameValue"
      :error-messages="errorsWrapper.name"
    />
  </v-form>
</template>

You can do the same thing for the useField().errorMessage field. Is it possible to implement this in vee-validate?

I've pushed the complete example with updated package versions to the same repository.

logaretm commented 1 year ago

The implication of this is it means I can no longer use computed anywhere in the codebase. It's not just errors that are affected, but also meta, and various other properties.

I will try to think of something.

EDIT:

Attempted to wrap them in the codebase, half of the tests are failing, I don't know why but seems like the wrapping behavior isn't exactly the same as having a computed directly exposed.

VitalijBukatkin commented 11 months ago

There is a similar problem with vee-validate and primevue. InputText with trim is also used. But in my case this is only in dialogues. With vanilla input, the error does not occur. For now, I decided to roll back to the latest version in which entering spaces works - 4.8.6.

Example project: https://stackblitz.com/edit/vee-validate-v4-prime-vue-jcuwbq?file=src%2FEditDialog.vue