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


相关推荐
gCode Teacher 格码致知1 分钟前
前端教学8:提高 CSS 选择器的优先级,有哪些方法?
前端·css·html5
u0111026756 分钟前
Canvas 导出 PNG 时 quality 参数为什么不起作用
前端·javascript·vue.js
众链网络12 分钟前
年卡跨淡旺季的有效期模型:不可用日期、次数与顺延规则
java·前端·数据库
2601_9498477516 分钟前
jose 跨端三方库仓颉适配全流程
前端·javascript·flutter
CappuccinoRose27 分钟前
滚动交互体系
前端·javascript·交互·html5·1024程序员节
时空节拍AI数字人30 分钟前
博物馆数字人讲解系统设计:知识库 schema、展项联动协议与时序控制
java·服务器·前端·人工智能·ai·语音识别
吴建旭 智宅焕31 分钟前
智能家居全国交付中前端工具与后端基础设施的系统集成架构:报价入口与交付兜底的闭环设计
前端·架构·智能家居
开开心心就好1 小时前
电脑小说阅读器,支持朗读和自定义皮肤
服务器·开发语言·javascript·算法·pdf·c#·音视频
夏天要喝冰可乐1 小时前
Codex 写 Three.js 大屏实录:800 行代码,和一条画反的弧线
前端·aigc
欣欣之王来了1 小时前
v-bind语法糖::属性名的简写方式
前端·学习·架构·项目·vue3教程