javascriptreactjsantd

Why number validate rule doesnt work in antd


I have a simple login form, but validation rule with type: 'number' for input item tn doesn't work. Even if I enter a number, I get 'tn' is not a valid number' in console.

    import React from 'react';
    import { Form, Input, Button, Checkbox } from 'antd';
    import { UserOutlined, LockOutlined } from '@ant-design/icons';
    import './style.css';
    
    export const LoginForm = () => {
      const onFinish = (values) => {
        console.log('Received values of form: ', values);
      };
    
      return (
        <Form
          name="login_form"
          className="login-form"
          initialValues={{
            remember: true,
          }}
          onFinish={onFinish}
        >
          <h3 className="main-label">LOG IN</h3>
          <Form.Item
            name="tn"
            rules={[
              {
                type: 'number',
                required: true,
                message: 'Wrong number',
              },
            ]}
          >
            <Input
              prefix={<UserOutlined className="site-form-item-icon" />}
              placeholder="Enter your tn"
            />
          </Form.Item>
          <Form.Item
            name="password"
            rules={[
              {
                required: true,
                message: 'Please input your password',
              },
            ]}
          >
            <Input
              prefix={<LockOutlined className="site-form-item-icon" />}
              type="password"
              placeholder="Password"
            />
          </Form.Item>
          <Form.Item>
            <Form.Item name="remember" valuePropName="checked" noStyle>
              <Checkbox>Remember me</Checkbox>
            </Form.Item>
          </Form.Item>
    
         ...
      );
    };

I tried other rules and they works fine. What's the problem with numbers?


Solution

  • Due to Ant Design's <Input/> component, it will store the number as a string even if the type props have been set.

    The first workaround is to just use Ant Design's <Input Number/> component, which doesn't store the number as a string (AFAIK without looking at the source). Although that component is quite nice, it does come with the arrows for adjusting the number, which isn't optimal if prompting for something like a zip code.

    After further digging, whether it is a real bug or an overlook, {type:number} won't get you anywhere when using Ant Design's <Input/> component.

    I would suggest you check out Issue #731, then check out Issue #10003 for more details. (there is some pretty neat validation code in both of those like this ... but just browse around and explore).

    I like the simplicity of just listing the rule sets without implementing a custom validator (especially for problems like number-only); however, it's not always possible.

    Here is some sample code that I use for my Zip Code validation. Note that you could always combine the message strings into one Promise.Reject() at the end of the validator, but I find it clutters up the screen for the user (especially with more than two validation error messages).

    <Form.Item
      validateTrigger="onBlur"
      name="ZipCode"
      label="Zip Code"
      hasFeedback
      rules={[
        {
          required: true,
          message: "Please enter zip code",
        },
        () => ({
          validator(_, value) {
            if (!value) {
              return Promise.reject();
            }
            if (isNaN(value)) {
              return Promise.reject("Zip code has to be a number.");
            }
            if (value.length < 5) {
              return Promise.reject("Zip code can't be less than 5 digits");
            }
            if (value.length > 5) {
              return Promise.reject("Zip code can't be more than 5 digits");
            }
            return Promise.resolve();
          },
        }),
      ]}
    >
      <Input />
    </Form.Item>;
    

    Edit: Not exactly sure if I just overlooked this or if they recently put it up, but there is a working input (like you want) using custom validation. I believe this CodePen will solve your problem.