12

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?

Alex Ironside
  • 4,658
  • 11
  • 59
  • 119
Srikanth Gowda
  • 6,163
  • 7
  • 19
  • 34
  • Isn’t there an `await` missing before the `request`? Like `return await request(`/api/getZipcodeInfo?zipcode=${zipcode}`);` Btw: nice article about async await: https://jakearchibald.com/2017/await-vs-return-vs-return-await/ – Matthi Nov 24 '18 at 09:52
  • 1
    Thank you for asking this question! – Alyssa Reyes Oct 14 '19 at 19:46

2 Answers2

10

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}`);
}
Alejandro
  • 5,834
  • 1
  • 19
  • 36
0

Example on how to apply form validation on button, which is not related to form on submit.

Button example:

<Button
    id="schematronBtn"
    className="m-2 float-left btn-primary"
    shape="round"
    type="primary"
    onClick={() => this.showSchematronModal()}
  >
    {t('rulesForm.schematronBtn')}
</Button>

Fields validation example:

showSchematronModal() {
  this.formRef.current.validateFields().then(() => { // validation succeeded
    const { selectStatus } = this.state;
    if (selectStatus === 'DRAFT' || selectStatus === 'PILOT') {
      this.generatedRuleSchematron(true);
    } else {
      this.setState({ isSchematronModalVisible: true });
    }
  }).catch(async e => { // validation failed, call some validation function
    if (e.errorFields) { // form has errorFields
      await this.onFinishFailed(e);
    }
  });
}
tdy
  • 36,675
  • 19
  • 86
  • 83