Vee-validate: Multiple v-models/values inside validation provider gives infinite loop

Created on 17 Feb 2020  路  17Comments  路  Source: logaretm/vee-validate

Versions

  • vee-validate: 3.2.1
  • vue: 2.6.10

Describe the bug
This is a copy of #2587 that got closed. I've attached a better demo.

It seems that when using a component with multiple v-models inside a validation provider the application hangs with an infinite loop.

To reproduce
Steps to reproduce the behavior:

  1. Go to demo link
  2. The Demo.vue-component contains a validation provider with a component inside.
  3. As soon as a v-model is added to the component the loop starts.

Demo link
https://codesandbox.io/s/codesandbox-mlioh

Desktop (please complete the following information):

  • OS: win10
  • Browser chrome
  • Version latest
馃悰 bug 馃洺 In PR

Most helpful comment

First, I'm very sorry that such a critical issue is taking a lot of time to fix. I have been dealing with a lot lately and didn't find time to maintain vee-validate as much as I used to. Anyways these days are behind me now.

The problem is mainly caused by the tree traversal done by the ValidationProvider and is amplified when two providers exist within one another by using either a component or slot. It isn't caused by multiple v-model within the template.

Here are a few scenarios and fixes I tried:

Detecting whether two providers exist within one another and stopping the traversal there

This works for slot but doesn't work for components that render a provider using a dynamic component because the tree shape is unknown then. In other words, the provider has no way to detect if it's rendering another provider.

Tagging VNodes rendered by the Provider with its own id and skipping traversal when there are conflicting ids (means there is another provider around)

This works for all cases when the VNode is actually a ValidationProvider node, custom wrappers which are the common way to use the ValidationProvider will bypass this method and won't solve the issue.


The only solution that works is that the provider should only be limited to exactly one model to watch, meaning the first v-model encountered in the traversal will be treated as the value to validate. This improves performance considerably and solves this issue completely but will cause radio inputs to stop being grouped together in the same provider.

Adding an exception for the Radio inputs won't work with custom components, and its easier to document workarounds for radio and checkboxes than to implement something that would work for native inputs and components alike.

I think this is a worthwhile trade, I'm looking for feedback here. You can test the fix by checking #2734

All 17 comments

The problem seems to occur when you have multiple v-models inside a validation-provider, even if the v-models are in different nested validation-providers.

I experimented before with halting tree traversal whenever a ValidationProvider is encountered, but it was unreliable. Will try again later this week.

Versions

vee-validate: 3.2.5
vue: 2.6.10

Describe the bug

Hi, I am also facing this issue.

I made a custom radio component for my form that takes an array of value and generates slots to display the radio buttons.

Without VeeValidate, it works perfectly and does what I want.

With VeeValidate it creates an infinite update loop.

To reproduce

Steps to reproduce the behavior:

  • Uncomment the ValidationProvider in Radios.vue

Demo Link :

https://codesandbox.io/s/vibrant-cloud-9t6dj

Desktop (please complete the following information):

OS: osx catalina
Browser chrome
Version latest

I am having the same issue as leo-martin except for the fact that I am using a custom select component. I am using the same versions of vee-validate and vue.

UPDATE I am not sure if this is helpful but when I incrementally installed previous versions of vee-validate the infinite loop stopped on version 3.0.6.

Any news?

I've got a similar issue: I have a component that has a :value set and responds to @input and contains a number of inputs inside the component. It uses these inputs to derive the value which it emits back to the parent.

Expected: It would validate on the custom component and not look at the inputs inside.
Actual: When I wrap my component in a validation provider it triggers the infinite loop.

I have a similar case to shaylinko30's.

Inside ValidationProvider I have a custom select component.
Recently I upgraded from version 3.0.3 to 3.2.5. In the previous version, the infinite loop does not appears.

I'm having the same problem using the date picker from V-Calendar.

I'm working on migrating to 3 from 2 and installed 3.2.5 but was getting the same infinite loop error.
I tried what @shaylinko30 said and reverted to 3.0.6 and the error is gone. So for now, I'll just roll with that until it seems safe to go with a newer version.

UPDATE: I just realized I need at least version 3.2.* to be able to use handleSubmit which is a big advantage with version 3. To get around this I found that I can use the older method in 3.0.6 called passes to accomplish this until I am able to safely update to 3.2.*

On another note, I'm not nesting any ValidationProvider components. I only have 2 ValidationProvider's with fields inside of a ValidationObserver wrapping my form. It seems like I have a very standard simple form following the documentation, and it works fine in 3.0.6. So I have no idea why the infinite loops happens for these other versions.

I had the same issue and here is my task manager after working with this plugin for a while
image

@Bibendus83 better open a separate issue for that (with ways to reproduce). Your comment just serves to pile on complaints for software you're getting for free. Be nice and constructive, ok?

@ul8 I think it's related considering the firefox memory leak is probably caused by the infinite loops error.
I didn't mean to be rude by any mean.

@Bibendus83 ah, misunderstood you there, cheers! Yep I have to kill the chrome tab too when that happens.

@ul8 I noticed that the error was not appearing if I reduced the amount of fields contained in the ValidationProvider element.
IMHO I think it's a memory leak issue that's always present but only when the amount of fields is too high the browser recognizes a huge amount of iterations and throws the infinite loop error.

@Bibendus83 not sure, because I had this issue with only an email & password field in a very simple form.

First, I'm very sorry that such a critical issue is taking a lot of time to fix. I have been dealing with a lot lately and didn't find time to maintain vee-validate as much as I used to. Anyways these days are behind me now.

The problem is mainly caused by the tree traversal done by the ValidationProvider and is amplified when two providers exist within one another by using either a component or slot. It isn't caused by multiple v-model within the template.

Here are a few scenarios and fixes I tried:

Detecting whether two providers exist within one another and stopping the traversal there

This works for slot but doesn't work for components that render a provider using a dynamic component because the tree shape is unknown then. In other words, the provider has no way to detect if it's rendering another provider.

Tagging VNodes rendered by the Provider with its own id and skipping traversal when there are conflicting ids (means there is another provider around)

This works for all cases when the VNode is actually a ValidationProvider node, custom wrappers which are the common way to use the ValidationProvider will bypass this method and won't solve the issue.


The only solution that works is that the provider should only be limited to exactly one model to watch, meaning the first v-model encountered in the traversal will be treated as the value to validate. This improves performance considerably and solves this issue completely but will cause radio inputs to stop being grouped together in the same provider.

Adding an exception for the Radio inputs won't work with custom components, and its easier to document workarounds for radio and checkboxes than to implement something that would work for native inputs and components alike.

I think this is a worthwhile trade, I'm looking for feedback here. You can test the fix by checking #2734

Was this page helpful?
0 / 5 - 0 ratings