Navigation Menu

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

Slots inside ValidationProviders: validation inside slot not working correctly in 'eager' mode #2185

Closed
rvdrijst opened this issue Jul 25, 2019 · 6 comments
Labels
🐛 bug Unintended behavior ☔ has workaround this issue has a workaround

Comments

@rvdrijst
Copy link

Versions

  • vee-validate: 2.2.13
  • vue: 2.6.10

Describe the bug
When using slots inside ValidationProvider, the inputs are recognized but event handlers are not bound correctly, leading to unexpected results.
This seems the result of a bug that shows itself in eager mode, but is also present in other modes, as explained below.

To reproduce
I've prepared a minimal example here:
https://codesandbox.io/embed/veevalidate-slotted-input-problem-example-z0786

There are two fields here: one inside the slot in the same file as the ValidationProvider (default slot content). The second has the slot filled in a parent component ExampleForm. The second field does not validate correctly.

Steps to reproduce the behavior:

  1. Focus on the first field, then blur it. The required validation will trigger (expected)
  2. Focus on the first field, start typing and the validation will change depending on the input instantly (expected in 'eager' mode)
  3. Now focus on the second field, then blur it. The required validation will trigger (expected)
  4. Focus on the second field again, start typing, and the validation will not trigger until you blur the second field again.

Expected behavior
In the second field, I expect the validation to work the same as in the first field.

Additional context
I've done a bit of debugging and it seems to be that addListeners is called quite a few times after every character that is typed. There, the onValidate listener is added on the input through addVNodeListener which eventually calls mergeVNodeListeners on node.data.on. In the first field, these listeners are nice and clean (only 1 or 2 on input and blur), but on the second field, they accummulate quite quickly (hundreds of event handlers per eventtype if you type a few characters) I suspect this is where something goes wrong, but I don't have enough insight into how this is supposed to work to know what exactly is happening here. Hopefully this is a helpful pointer.

Note that this rapidly growing event handler list is also present in 'normal' mode, but somehow it doesn't interfere with the actual validation.

To see what happens, put a breakpoint in the code at mergeVNodeListeners and type a few characters in each field. Stepping through the calls to mergeVNodeListeners you will see that obj grows very quickly for the second field (although the first few calls seem alright, suddenly there is an 'old' version that remembers listeners). The first fields stays nice and clean.

@rvdrijst
Copy link
Author

I've found a weird work-around that might also point in the right direction for a real solution.

If I wrap the input in a template with scope props (even though the slot has no props) it works as expected.

<template v-slot:default="props">
   <input .../>
</template>

Adapted example:
https://codesandbox.io/embed/veevalidate-slotted-input-problem-example-f1xvf

@logaretm
Copy link
Owner

logaretm commented Jul 26, 2019

That's a very good catch, I spent a couple of hours figuring what was the issue. The problem wasn't actually the growing list of listeners (now fixed) as they are still were being added as per the computeModeSetting correctly.

The problem was in the shouldValidate method as it detected the value before it was even updated, resulting in the validator thinking the value did not change between renders, this is because the explicit field is rendered in the parent scope, not inside the form-item scope.

This is fixed by not syncing the value in the onInput listener, this should allow the re-render to detect the change correctly.

Thanks for reporting this!

@rvdrijst
Copy link
Author

Cheers, thanks for the fix and the explanation!
Any idea on when this will make it into a release?

BTW great work on this plugin!

@logaretm
Copy link
Owner

@rvdrijst I do releases on a weekly basis, so there should be one coming up in the next couple of days.

@logaretm
Copy link
Owner

This was reverted because it introduces more bugs, I will try to investigate the issue again.

@logaretm
Copy link
Owner

Fixed by 07fa140

AlvaroBrey pushed a commit to imagames/vee-validate that referenced this issue Jan 7, 2020
…garetm/vee-validate

* upstream/v2: (689 commits)
  fix: update v3 links and repo links closes logaretm#2467
  chore: add v3 docs link
  docs: add note for read me
  Added missing changes flag in FieldFlags definition (logaretm#2218)
  docs: uneeded document about escaping regex
  docs: fix the regex example
  chore: bump to 2.2.15
  revert: logaretm#2185 closes logaretm#2209
  chore: bump to 2.2.14
  chore: upgrade dependencies
  fix: mark vee-validate handlers so they get deduped
  Revert "fix: don't sync the value in an event handler closes logaretm#2185"
  chore: rm .DS_Store
  test: fix failing tests due to punctation
  test: fix failing tests
  Remove periods at end of validation messages (logaretm#2195)
  alpha_helper.js: regex for persian characters has been added (logaretm#2190)
  fix: don't sync the value in an event handler closes logaretm#2185
  fix: cleanup events before adding new ones
  Update displaying-errors.md (logaretm#2186)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Unintended behavior ☔ has workaround this issue has a workaround
Projects
None yet
Development

No branches or pull requests

2 participants