Antd Custom Validator and validateFields Are Not Working Together as Expected

I'm working on a form (Ant Design <Form>) where I want a custom validation of phone number (as it depends on country field and has some extra logic), and other fields validated by antd built-in features, so when user submits the form I want all fields to be validated with validateFields() passed as an array of field names showing validation errors as usual (red message underneath and an error message in console), but all I'm getting is just a warning message in the console.

Here's a minimal reproduction

Am I missing something about how validator function works?

3 Answers

make a if else check in your validatePhone function if value is not empty then run your code and if value is empty simply send a callback in else condition. like that

const validatePhone = (rule: any, value: any, callback: any) => {
  if (value) {
    const countryName = form.getFieldValue('country');
    const country = CountryList.getCode(countryName);
    const phoneNumber = parsePhoneNumberFromString(value, country as CountryCode);
    console.log(form.getFieldValue('country'));
    if (countryName && phoneNumber && phoneNumber.isValid()) {
      updatePhonePrefix(prefix.concat(phoneNumber.countryCallingCode as string));
      callback();
    } else {
      callback(`Phone number is not valid for ${countryName}`);
    }
  } else {
    callback();
  }
};

what the antd docs recommend is to use async or try-catch block

option 1:

const validatePhone = async (rule, value) => {
  // check failing condition
  throw new Error('Something wrong!');
}

option 2:

const validatePhone = (rule, value, callback) => {
  try {
    throw new Error('Something wrong!');
  } catch (err) {
    callback(err);
  }
}

Here how I handled the error in antd form

import React, { useState } from 'react';
import { Form, Input } from 'antd';

function MyCustomForm(props: any) {
  const [form] = Form.useForm();
  const [validateFieldsName, setValidateFieldsName] = useState<string[]>([]);

  const handleValidateFieldNames = (name: string) => {
    const isFieldName = validateFieldsName.find(
      (fieldName) => fieldName === name
    );
    if (isFieldName) return 'onChange';
    return 'onBlur';
  };

  return (
    <Form form={form} layout="vertical">
      <Form.Item
        name="contactNumber"
        label="Contact Number"
        validateTrigger={handleValidateFieldNames('contactNumber')}
        rules={[
          {
            required: true,
            message: 'Please enter contact number!',
          },
          {
            validator(_, value) {
              if (!value || value.length === 10) {
                return Promise.resolve();
              }
              return Promise.reject('Please enter 10 digit Number!');
            },
          },
        ]}
      >
        <Input
          type="number"
          placeholder="Contact number"
          onBlur={() =>
            setValidateFieldsName([...validateFieldsName, 'contactNumber'])
          }
        />
      </Form.Item>
    </Form>
  );
}

export default MyCustomForm;
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.

Share this article
Twitter Facebook Pinterest