Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 320
tzi0 Avatar asked Jan 24 '23 14:01

tzi0


2 Answers

The built in method does not work as Ant Design v4 recognises inputs as string. The solution is to use Regex.

<Form.Item
    name="myNumber"
    rules={[{ 
        required: true, 
        message: "A value must be entered",
        pattern: new RegExp(/^[0-9]+$/)
    }]}
>
    <Input
        placeholder="x"
        maxLength={5}
    />
</Form.Item>

It's also worth noting that the getFieldDecorator() method is basically redundant as of v4 of Ant Design. They should also better advertise that.

The above Regex pattern enforces integers and disallows decimals.

like image 130
MSOACC Avatar answered Jan 27 '23 02:01

MSOACC


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.

like image 44
spencer741 Avatar answered Jan 27 '23 03:01

spencer741