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

Async validator does not work after error #204

Closed
zalishchuk opened this issue Dec 9, 2017 · 19 comments
Closed

Async validator does not work after error #204

zalishchuk opened this issue Dec 9, 2017 · 19 comments

Comments

@zalishchuk
Copy link

zalishchuk commented Dec 9, 2017

Why async validator stops working after resolving first error?

https://github.com/zalishchuk/react-form-async-validators

Try to type anything into field, it run validator every time, but if you will type error (to resolve object with error) it will fail and die then, validator will never run again. Bug or feature and how can I disable this logic?

Update: fixed that by adding synchronous validator.


Another question is how can I do things in custom text input onChange method after field finished validating. Something like waitValidation method in fieldApi to use it like this:

const onChange = async event => {
  event.persist();

  const {
    onChange,
    fieldApi: { setValue, waitValidation },
  } = this.props;

  setValue(event.target.value);
  
  await waitValidation();

  onChange(event); // will be executed after field finished validating
};
@zalishchuk zalishchuk changed the title Async validator does not validate after error Async validator does not work after error Dec 10, 2017
@zalishchuk
Copy link
Author

zalishchuk commented Dec 10, 2017

Since async validations are running on setTouched event, this method should be asynchronous. Feature can be used in custom inputs which have async validations.

#205

Example:

import React, { Component } from 'react';
import { FormField } from 'react-form';

@FormField
class Text extends Component {
  render() {
    const {
      fieldApi: {
        getValue,
        setValue,
        setTouched,
        getError,
        getWarning,
        getSuccess,
      },
      onChange,
      onBlur,
      ...rest
    } = this.props;

    return (
      <input
        {...rest}
        value={getValue() || ''}
        onChange={async event => {
          event.persist();

          setValue(event.target.value);

          await setTouched(); // this will trigger and wait for validations

          // actual values after validation ended
          console.log(getError(), getWarning(), getSuccess());

          if (onChange) {
            onChange(event);
          }
        }}
        onBlur={event => {
          setTouched();

          if (onBlur) {
            onBlur(event);
          }
        }}
      />
    );
  }
}

export default TextAsync;

@joepuzzo
Copy link
Contributor

Hmm i dont think this is what we want. setTouched should only care about one thing. Setting the field to touched. And on change should only care about one thing, did the field change. A side affect, yes is that async validation should get triggered, but that does not change the fact that the field changed.

@zalishchuk
Copy link
Author

What do you propose to do? How can we get errors, warnings, successes in fields which have asynchronous validation? My solution does not break anything, just gives the opportunity to wait before validation is complete and get actual information about field.

@joepuzzo
Copy link
Contributor

you know who is validating and when they are done based on the validating props. That being said maybe i could add callback that gets triggered when async validation is complete.

@cthurston
Copy link

I ran into this as well. @zalishchuk What did you mean when you said "Update: fixed that by adding synchronous validator." Does that mean that you just gave up on async and are using synchronous validation or that by adding synchronous validation it somehow forced the async to recheck after error?

@zalishchuk
Copy link
Author

adding synchronous validation it somehow forced the async to recheck after error?

@cthurston Async validators are not running until error becomes null. So, yes, I just add a simple synchronous validator and that fixed my problem.

@joepuzzo
Copy link
Contributor

Im still a little confused on the issue. is it that async validation is not running when a syncronous validation has already occurred on that field?

@cthurston
Copy link

If async validation produces an error there is no event that will clear it out.

If you edit and blur the field again, it will not re-run the async validation because the error is still there.

By adding a synchronous validation to the field it forces the error to be cleared out onChange. Therefore the async validation will run again.

@zalishchuk
Copy link
Author

zalishchuk commented Dec 13, 2017

@joepuzzo
Copy link
Contributor

A successful validation would clear it out though? would it not?

@zalishchuk
Copy link
Author

If async validator produces an error once, field validation will not invoke. Check out my test repository and after try to add a simple synchronous validator for name field.

@joepuzzo
Copy link
Contributor

For example, in docs go to the async section and do the following.

  1. Type Joe and tabb out of field, this will trigger async validation and set an error
  2. Go back into field and type reject, then tab out again, this will trigger async validation that will throw an exception
  3. Go back into field one more time and do step 1 again. This will remove the failure and set the error.

@zalishchuk
Copy link
Author

@joepuzzo there is an errorValidator that synchronously validates username field, if you will remove validateError and validateSuccess (not necessary) field validation will not work after first error.

@joepuzzo
Copy link
Contributor

Ok let me try this locally

@joepuzzo
Copy link
Contributor

Ohh i see now.. ok i have meeting rn but ima look into this after because im starting to now think this is bug.

@joepuzzo
Copy link
Contributor

Wooooowww i am stupid

@joepuzzo
Copy link
Contributor

Somewhere in my code i was doing the following

return Object.assign(this.props.formState.errors, this.props.formState.asyncErrors );

It should have been

return Object.assign( {}, this.props.formState.errors, this.props.formState.asyncErrors );

@joepuzzo
Copy link
Contributor

So i was merging errors and async errors internally.. they should only be merged for the user.

@joepuzzo
Copy link
Contributor

joepuzzo commented Dec 13, 2017

Ok this is fixed in 2.14.3!!!

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

No branches or pull requests

3 participants