ember-changeset icon indicating copy to clipboard operation
ember-changeset copied to clipboard

Async validator question

Open brancusi opened this issue 9 years ago • 11 comments

Hi,

Is there a way to check if a changeset has changed since it was last validated?

Ideally setting any prop: changeset.set('prop', 1) will turn changeset.get('isValid') false, until all validators (async here is the issue) resolve.

This would allow us to disable UI until we know for certain that everything is resolved and valid.

Currently, if there is a slow async validator, the changeset will be in isValid true, but in reality, it is still unresolved, and therefor, the user may proceed to submit and then the world falls apart.

Let me know what you think.

Thanks

brancusi avatar Sep 02 '16 01:09 brancusi

Hey, good question. Ideally it should be invalid during an async validation. I'll have to think about how to implement it in a nice way, but yeah I agree

poteto avatar Sep 03 '16 04:09 poteto

Excellent. Thank you

brancusi avatar Sep 03 '16 06:09 brancusi

Can you give d633440b0aafbeb0a1c484ca53b87aa60b244ad9 a whirl @brancusi? Let me know if that fixes the issue for you - isValid / isInvalid should now take into account any async validation running

poteto avatar Sep 06 '16 00:09 poteto

Thanks @poteto I have been trying it out.

Just want to add a scenario and see what your thoughts are.

Basically, I would like to run a uniqueness validation. This will hit a unique_check endpoint.

I see now that when I changeset.set("prop", val) it does indeed change the isValid to false until resolved, but here are a few concerns.

  1. Debouncing the input. I currently debounce outside of the validator which leads us to the next issue
  2. How can we set the changeset to pending so that it's isValid == false while we debounce? Since we debounce outside the validator, we don't changeset.set... until the debounce completes, for this reason, the changeset is never directly touched during the debounce delay, and the user could trigger a submit before validation. (I really need a twiddle on this I know)

Lastly, I notice that when we changeset.set("prop", val) and there is an async validator on prop, if we continue to set new values before the validator resolves, anything after gets overwritten when the validator resolves. So you get a broken typing experience.

That is if of course if you bind the value of the input field to {{one-way-input changeset.prop}}. Not sure if that is a bad idea, but even if we don't bind, we still have potential issues with out of order async validations clobbering data.

If we could achieve something like: changeset.clearValidations() to put it back into pending. That could happen as the user starts typing, then debounce and once resolved it would all refire. I would like to avoid tracking state outside of the changeset for things like disabling a submit button.

brancusi avatar Sep 06 '16 21:09 brancusi

Hmm, thanks for letting me know. It'll definitely be easier to visualize if you could make a simple twiddle

poteto avatar Sep 07 '16 18:09 poteto

So check it out with a 1 sec delay: https://ember-twiddle.com/99807edeadef70a3de0973ab6b1a99f8?fileTreeShown=false&openFiles=validators.uniqueness.js%2C

Thanks

brancusi avatar Sep 08 '16 01:09 brancusi

Hi @poteto, any ideas on this? Please let me know if you want a different scenario in a twiddle.

Thank you

brancusi avatar Sep 14 '16 16:09 brancusi

:+1:

Just my two cents because my needs are (almost) exactly the same. This is a really common scenario :

Given a form with an email input which needs a uniqueness validation check,

  1. The user writes some characters in the email input
  2. After some inactivity on this input (maybe 1s), the uniqueness email validation is triggered.

Then, either:

  • The user has written some new characters => the uniqueness validation is now outdated and should be ignored
  • Or the user did not change this input (but it could have changed another one!) => the uniqueness validation is still up-to-date and should display an error if the email already exists

To recap, ember-changeset needs the following features to resolve this scenario (some of them are probably already implemented) :

  • Delay before triggering the validations (probably related to #110)
  • Asynchronous validations : the uniqueness validation is done through a server check
  • Per-property validations : the user can change another input without triggering again the email validation
  • Per-property validation state : the email async validation should be ignored when the user changes the email input value while the validation is still pending

Do ember-changeset/ember-changeset-validation aim to solve this problem ?

lcoq avatar Oct 07 '16 10:10 lcoq

I have the same use-case for validating serial numbers. I've looked at the skipValidate. It can work but because it applies to the entire changeset and not just a single property, it makes ugly code to trigger validation on that one property only after debouncing but keep validation on all other properties as they're modified.

cristinawithout avatar Feb 22 '18 22:02 cristinawithout

Does anybody have a workaround for this issue? Because right now async validations on uniqueness seem te be useless because of the strange way the input field is working with an async validator attached to it..

A-Industry avatar Aug 09 '18 14:08 A-Industry

this worked for me https://gist.github.com/alexdiliberto/b3cf1bee63d93980aec56b7aeb0369f6

jaydev avatar Oct 09 '18 17:10 jaydev