Async form field validation in ant design

Srikanth Gowda picture Srikanth Gowda · Nov 23, 2018 · Viewed 7.2k times · Source

How to validate form fields asynchronously in ant design?

 <FormItem>
     {getFieldDecorator('zipcode', {
       initialValue: `${customer && customer.zipcode ? customer.zipcode : ''}`,
       rules: [
         // { required: true, message: 'Please input your Zipcode' },
         { validator: this.handlezipCodeChange },
       ],
     })(
       <Input
         prefix={
           <Icon type="zipcode" style={{ color: 'rgba(0,0,0,.25)', visibility: 'hidden' }} />
         }
         type="number"
         placeholder="Zipcode"
         // onChange={this.handlezipCodeChange}
       />
     )}
</FormItem>

function call

  handlezipCodeChange = (rule, value, callback) => {
    if (!value) {
      callback('Please input your zipcode');
    }
    if (value.length < 5) {
      callback('Please enter minimum length of 5');
    }
    if (value.length > 5) {
      callback('Please enter maximum length of 5');
    }
    if (value.length === 5) {
      const validateZipCode = validateZipcode(value);
      if (
        validateZipCode &&
        validateZipCode.result &&
        validateZipCode.result.zipcodeInfo === null
      ) {
        callback('Seems to be Invalid Zipcode');
      } else {
        callback();
      }
    }
  };

export async function validateZipcode(zipcode) {
  return request(`/api/getZipcodeInfo?zipcode=${zipcode}`);
}

How to show the error message from api response? As api call takes some time to complete at that time the validation function call get executed completely before api request complete. So how can i show the error message?

Answer

Alex picture Alex · Nov 24, 2018

You're missing await before validateZipcode and async before handlezipCodeChange:

handlezipCodeChange = async (rule, value, callback) => {
   ...
  if (value.length === 5) {
      const validateZipCode = await validateZipcode(value);
     ...
}

also, as mentioned in comment, you need to add await to your validateZipcode function:

export async function validateZipcode(zipcode) {
  return await request(`/api/getZipcodeInfo?zipcode=${zipcode}`);
}

You need to add it because actually, it's impossible to catch completeness of async operation in sync function.

Other solution is to unmark async from validateZipcode, and next use it as Promise-based:

handlezipCodeChange = (...) => {
  ...
  if (value.length === 5) {
    const successHandler = ({result = {}}) => result.zipcodeInfo === null ? callback('Seems to be Invalid Zipcode') : callback();

    validateZipcode(value)
      .then(successHandler)
      .catch( error => callback("Can't validate zip code") );

  }
}

export function validateZipcode(zipcode) {
  return request(`/api/getZipcodeInfo?zipcode=${zipcode}`);
}