【React】实现TagInput输入框,可以输入多个邮箱并校验是否合法

背景

需要实现一个类似Select组件的tags模式的输入框,输入一个邮箱后,回车,会显示成tag样式,也可以删除每一个tag。

实现

技术栈:react-tag-input-component + Antd

目前Antd没有提供现成的组件,可以使用react-tag-input-component,回车生成tag的时候进行校验邮箱是否合法,并显示错误提示

在进行表单提交的时候,也可以对tags进行非空和合法性校验。

EmailsFormInput/index.tsx:

javascript 复制代码
import { Form, FormItemProps } from 'antd';
import { forwardRef, useImperativeHandle, useState } from 'react';
import { TagsInput, TagsInputProps } from 'react-tag-input-component';
import styles from './index.module.less';

interface Props {
  formItemProps: FormItemProps;
  tagsInputProps: TagsInputProps;
}

const EmailErrorText = 'Please enter a valid email';
const EmailsEmptyErrorText = 'Please enter email';
const EmailReg = /^[\w.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(,[\w.-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})*$/g;

export const EmailsFormInput = forwardRef(({ formItemProps, tagsInputProps }: Props, ref: any) => {
  const [emailErrorTip, setEmailErrorTip] = useState<string>('');

  const handleValidateEmail = (emails: string[]) => {
    // 必填
    if (!emails?.length) {
      setEmailErrorTip(EmailsEmptyErrorText);
      return false;
    }
    // 邮箱格式是否正确
    if (!emails?.every((e) => new RegExp(EmailReg).test(e))) {
      setEmailErrorTip(EmailErrorText);
      return false;
    }
    return true;
  };

  useImperativeHandle(ref, () => ({
    // 暴露对emails的校验方法
    handleValidateEmail,
  }));

  return (
    // validateStatus 和 help 用于错误提示
    <Form.Item {...formItemProps} help={emailErrorTip} validateStatus="error" className={styles.tagInputFormItem}>
      <div className={styles.tagInputContainer}>
        <TagsInput
          placeHolder="Input email and enter to add more"
          classNames={{ tag: styles.tagContainer, input: styles.inputContainer }}
          {...tagsInputProps}
          onKeyUp={(e) => {
            if (e.key === 'Backspace') {
              // 删除操作的时候,需要清空错误提示
              setEmailErrorTip('');
            }
          }}
          beforeAddValidate={(tag: string) => {
            // 添加tag前对输入的字符进行校验
            if (tag && new RegExp(EmailReg).test(tag)) {
              setEmailErrorTip('');
              return true;
            }
            setEmailErrorTip(EmailErrorText);
            return false;
          }}
        />
      </div>
    </Form.Item>
  );
});

EmailsFormInput/index.module.less: 修改ui以适应Antd的设计风格

css 复制代码
.tagInputFormItem {
  .tagInputContainer {
    div:first-child {
      padding: 1px 2px;
      --rti-main: rgb(36, 126, 252);
      border: 1px solid #ccc;
      min-height: 54px;
      display: flex;
      justify-content: flex-start;
      align-items: flex-start;
    }
  }
  .tagContainer {
    background-color: rgba(0, 0, 0, 0.06);
    margin: 2px 4px 2px 0;
    height: 24px;
    button {
      height: 10px;
      width: 10px;
      font-size: 10px;
      color: rgba(0, 0, 0, 0.45);
    }
  }

  .inputContainer {
    height: 28px;
    width: 40%;
    margin-left: 8px;
    color: rgba(0, 0, 0, 0.88);
  }
}

使用

javascript 复制代码
<EmailsFormInput
  formItemProps={{
    name: 'approver_list',
    label: 'Approver(s)',
    rules: [
      {
        required: true,
        message: 'Approver',
      },
    ],
  }}
  tagsInputProps={{ value: approvers, onChange: setApprovers }}
  ref={approverEmailInputRef}
/>


相关推荐
web守墓人1 小时前
【前端】ikun-markdown: 纯js实现markdown到富文本html的转换库
前端·javascript·html
Savior`L1 小时前
CSS知识复习5
前端·css
许白掰1 小时前
Linux入门篇学习——Linux 工具之 make 工具和 makefile 文件
linux·运维·服务器·前端·学习·编辑器
中微子5 小时前
🔥 React Context 面试必考!从源码到实战的完整攻略 | 99%的人都不知道的性能陷阱
前端·react.js
秋田君6 小时前
深入理解JavaScript设计模式之命令模式
javascript·设计模式·命令模式
中微子6 小时前
React 状态管理 源码深度解析
前端·react.js
风吹落叶花飘荡7 小时前
2025 Next.js项目提前编译并在服务器
服务器·开发语言·javascript
加减法原则7 小时前
Vue3 组合式函数:让你的代码复用如丝般顺滑
前端·vue.js
yanlele8 小时前
我用爬虫抓取了 25 年 6 月掘金热门面试文章
前端·javascript·面试
lichenyang4538 小时前
React移动端开发项目优化
前端·react.js·前端框架