【React + Ant Design】表单如何在前置项未填写时禁止后置项交互并提示

在 react + antd 中,对表单做在前置项未填写时禁用后置项交互并提示的效果。

情景

最近有这么个需求,某个业务中,要填写一张表单,其中有这样两项:选择数据连接和选择数据表,数据表是数据连接下所拥有的表。通常,没选数据连接,数据表就拿不到数据,点击下拉无非是个空的框,这并不影响正常使用,大家都能接收,一般也不会做更精细的要求。但我们的产品要求实现以下效果:未选择数据连接时,无法点击数据表,同时在数据连接下面提示,请选择数据连接。

大致意思就是,没选数据连接的时候,不让下拉数据表选项,点击了就提示你数据连接还没选呢!

思路

项目用的 UI 库是 ant design pro,表单用到了 ProForm, FormItem 以及 Select 等众多输入组件。

笔者最初想着 antd 的表单项能不能为警告消息绑定自定义的变量,这样点击选择数据表的时候判断一下,给数据连接那边挂上消息提示不就好了。很可惜,阅读表单以及表单项的 Api 文档后,发现没有提供绑定自定义消息变量的接口。

没事,继续读 Api 文档,总有别的出路。果然,其中表单 FromInstance 的一项引起了我的注意:validateFields(nameList?: NamePath[]),正常情况下,表单的校验是在 onChange 或者 onSubmit 时自动触发的,validateFields则使得我们能手动触发对指定表单项的检验,那可不就来了嘛,点击选择数据表时,校验一下数据连接有了没,没有的话把数据表选项的点击给阻止掉即可。

方案

  1. 绑定到表单的 ref 实例
  2. 在 数据连接的 组件上添加规则,检验 required
  3. 在 Select 组件外包裹一层 div,在这上面将进行 Select 点击事件的冒泡组织
  4. Select 外层 div 上传入 onPointerDown 事件(为什么不是 onClick 和 onMouseDown,因为通过尝试发现 Select 的点击事件作用在 onPointerDown 上),在点击时,触发对数据连接项的检验,如果检验不通过就阻止 Select 的冒泡点击

伪代码

ts 复制代码
const formRef = useRef<ProFormInstance>();

<ProForm
  layout="horizontal"
  validateTrigger={['onSubmit']}
  formRef={formRef}
>
  <FormItem required name="conn" label="数据连接" rules={[
    { required: true, message: '请选择数据连接' }
  ]}>
    <Select options={conns} />
  </FormItem>
  <FormItem required name="table" label="数据表" rules={[
    { required: true, message: '请选择数据表' }
  }]>
    <div onPointerDown={(e) => {
      formRef.current.validateFields(['conn'])
        .catch(err => {
          console.error(err);
          e.preventDefault();
        })
      }}
    >
      <Select options={tables} />
    </div>
  </FormItem>
</ProForm>

至此,基本达成需求的效果,Bingo!

相关推荐
NetX行者几秒前
基于Vue 3的AI前端框架汇总及工具对比表
前端·vue.js·人工智能·前端框架·开源
独立开阀者_FwtCoder几秒前
手握两大前端框架,Vercel 再出手拿下 Nuxt.js,对前端有什么影响?
前端·javascript·vue.js
独立开阀者_FwtCoder1 分钟前
弃用 html2canvas!快 93 倍的截图神器!
前端·javascript·vue.js
weixin_3993806916 分钟前
TongWeb8.0.9.0.3部署后端应用,前端访问后端报405(by sy+lqw)
前端
伍哥的传说36 分钟前
H3初识——入门介绍之常用中间件
前端·javascript·react.js·中间件·前端框架·node.js·ecmascript
AA-代码批发V哥38 分钟前
JavaScript之数组方法详解
javascript
洛小豆1 小时前
深入理解Pinia:Options API vs Composition API两种Store定义方式完全指南
前端·javascript·vue.js
Jokerator1 小时前
Vue 2现代模式打包:双包架构下的性能突围战
javascript·vue.js
洛小豆1 小时前
JavaScript 对象属性访问的那些坑:她问我为什么用 result.id 而不是 result['id']?我说我不知道...
前端·javascript·vue.js
叹一曲当时只道是寻常1 小时前
Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
前端·golang