【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}
/>


相关推荐
哇哦谢谢你4 分钟前
vue-cli脚手架是如何读取vue.config.js的
javascript·vue.js·node.js
CodeClimb8 分钟前
【华为OD-E卷 - 120 分割数组的最大差值 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
虾球xz1 小时前
游戏引擎学习第96天
前端·学习·游戏引擎
A&long@20201 小时前
【浏览器多开】Google Chrome 谷歌浏览器分身术
前端·chrome
海上彼尚1 小时前
ollama 基本使用教程
前端·ai
吴永琦(桂林电子科技大学)1 小时前
Generate html
前端·html
scimence2 小时前
html 列动态布局
前端·css·html·列动态布局
秋淮安2 小时前
Web前端开发--HTML
前端
黑客老李2 小时前
一次使用十六进制溢出绕过 WAF实现XSS的经历
java·运维·服务器·前端·sql·学习·xss
幸运小圣2 小时前
LeetCode热题100- 轮转数组【JavaScript讲解】
javascript·算法·leetcode