封装一个可回车事件,不能输入配置项options没有的值的AutoComplete

要想AutoComplete支持回车事件,onKeyDown方法是用不了的,这一点在antd官方4.24.16中并没有提及。但是我们可以追踪到AutoComplete组件的源码,虽然并不能看很懂,但是可以看出组件是InternalSelectProps,RefSelectProps的共同构成,这里就不探究dataSource结构了。
在这里插入图片描述
最终逐步追击到了一个包含多个属性和方法的接口SelectProps
在这里插入图片描述
在这里插入图片描述
可见HTMLInputElement类型使用的是onInputKeyDown,不然我们再佐证一下
在这里插入图片描述
在这里插入图片描述
由此可知,虽然官方文档中AutoComplete组件并没有暴露出onInputKeyDown这一API,但是我们通过自己的逐步探索还是定位到了这一API。
现在我们来封装AutoComplete,要求暴露出一个bool值属性,当为true时候可以输入与配置项options不一样的value,当为false的时候不可以输入配置项里没有的value,当光标移走和回车事件的时候,AutoComplete值为空

import React, { useState,useRef } from 'react';
import { AutoComplete } from 'antd';

const CustomAutoComplete = ({ allowCustomInput,onInputKeyDown, ...rest }) => {
  const [inputValue, setInputValue] = useState('');
  const inputRef = useRef(null);

  const handleSearch = (value) => {
    setInputValue(value);
  };

  const handleSelect = (value) => {
    setInputValue(value);
  };

  const handleBlur = () => {
    if (!allowCustomInput && rest.options && !rest.options.some(item => item.value === inputValue)) {
      setInputValue('');
    }
  };

  const handleKeyDown = (e) => {
    if ((e.keyCode === 13||e.code === 'Enter'||e.key==='Enter') && !allowCustomInput && rest.options && !rest.options.some(item => item.value === inputValue)) {
      setInputValue('');
    }
    if(onInputKeyDown){
      onInputKeyDown(e)
    }
  };

  return (
    <AutoComplete
      {...rest}
      value={inputValue}
      onSelect={handleSelect}
      onSearch={handleSearch}
      ref={inputRef} 
      onBlur={handleBlur} 
      onInputKeyDown={handleKeyDown}
    />
  );
};

export default CustomAutoComplete;
  <Form.Item
        label={item.title}
        name={[`${formItemName}`, `${item.attributeUnique}`]}
        key={item.dataIndex}
      >
<CustomAutoComplete
          allowClear
          allowCustomInput={false}
          options={array}
          style={{ width: '200px', marginTop: '12px' }}
          onInputKeyDown={e=>{
            if(e.code=='Enter'){
              if(formSearchRef?.current){
              formSearchRef.current.submit();
              }
            }
          }}
          filterOption={(inputValue, option) =>
            option.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
          }
        />
    </Form.Item>

PS:“antd”: “4.16.13”
当CustomAutoComplete外面包裹着form表单时候,虽然CustomAutoComplete的值清空了,但是form表单给CustomAutoComplete的那个绑定name并没有清空,如何能让form表单绑定name也对应清空,目前我还没想出办法,也许可能要改造form表单,心累。。。。。。

PSS: 当formitem里面包裹的是AutoComplete官方控件,其在唤起allowClear时候,外面包裹的form表单项是更新了的,当我们自自定义控件就不行,这其中是因为Form表单的设计和实现。

在 Ant Design 中,表单项的值是由 Form 组件统一管理的。当 AutoComplete 组件的值发生变化时,如果它被包裹在一个Form.Item 中,Form 会自动监听到这个值的变化,并更新相应的表单字段的值。这是 Ant Design Form 组件的内置行为,不需要额外的配置或操作。

当用户点击清除按钮时,AutoComplete 组件会自动清空输入框的值,这不会影响到表单项的值。所以,当 AutoComplete 组件的值被清空时,Form 会自动更新表单字段的值,因此外面包裹的 form 表单项也会被清除。

对于自定义组件,如果其内部的值变化并不是通过 Ant Design 提供的特定事件触发的,那么 Form 组件就无法自动监听到这种变化。
CustomAutoComplete 组件是一个自定义组件,它的值变化是在组件内部通过 onSearch,onInputKeyDown,onBlur方法或其他自定义的事件触发的,并不是由 Ant Design 提供的事件。
因此,Form 组件并不知道 CustomAutoComplete 组件的值发生了变化,也就无法自动更新表单字段的值。Form.Item 的 name 属性依然是 [${formItemName}, ${item.attributeUnique}],它并没有直接与 CustomAutoComplete 的输入值进行绑定,所以即使输入值被置为空值,Form.Item 的字段仍然有值。

为了让 Form 组件能够监听到 CustomAutoComplete 组件的值变化并更新表单字段的值,需要在 CustomAutoComplete 组件内部主动触发 Ant Design 提供的事件,比如调用 Form.Item 的 onChange 方法来通知 Form 组件。这样,Form 组件才能正确地监听到 CustomAutoComplete 组件的值变化并更新表单字段的值。

更改CustomAutoComplete组件:

import React, { useState, useRef } from 'react';
import { AutoComplete } from 'antd';

const CustomAutoComplete = ({ allowCustomInput = true, onInputKeyDown, onClear, ...rest }) => {
  const [inputValue, setInputValue] = useState('');
  const inputRef = useRef(null);

  const handleSearch = (value) => {
    setInputValue(value);
  };

  const handleSelect = (value) => {
    setInputValue(value);
  };

  const handleBlur = () => {
    if (!allowCustomInput && rest.options && !rest.options.some(item => item.value === inputValue)) {
      setInputValue('');
      if (onClear) {
        onClear(); // 调用 onClear 回调函数
      }
    }
  };

  const handleKeyDown = (e) => {
    if ((e.keyCode === 13 || e.code === 'Enter' || e.key === 'Enter') && !allowCustomInput && rest.options && !rest.options.some(item => item.value === inputValue)) {
      setInputValue('');
      if (onClear) {
        onClear(); // 调用 onClear 回调函数
      }
    }
    if (onInputKeyDown) {
      onInputKeyDown(e);
    }
  };

  return (
    <AutoComplete
      {...rest}
      value={inputValue}
      onSelect={handleSelect}
      onSearch={handleSearch}
      ref={inputRef}
      onBlur={handleBlur}
      onInputKeyDown={handleKeyDown}
    />
  );
};

export default CustomAutoComplete;

  <Form.Item
        label={item.title}
        name={[`${formItemName}`, `${item.attributeUnique}`]}
        key={item.dataIndex}
      >
        <CustomAutoComplete
          allowClear
          allowCustomInput={false}
          options={resourceOptionList}
          style={{ width: '200px', marginTop: '12px' }}
          onClear={() => {
            // 处理清空操作,例如更新表单字段的值
            formSearch.setFieldsValue({
              [`${formItemName}`]: {
                [attributeUnique]: undefined,
              },
            });
          }}
        />
      </Form.Item>

除此之外,还有其他可能的思路:

  1. 使用 React Context: 可以使用 React Context 来共享表单字段的值和更新方法,这样
    CustomAutoComplete 组件就可以通过 Context 来更新表单字段的值,而无需直接依赖于 Form 组件。
  2. 使用自定义钩子: 可以编写一个自定义钩子来管理表单字段的值和更新方法,并在 CustomAutoComplete
    组件中使用这个钩子来更新表单字段的值。
  3. 通过父组件传递值: 在父组件中监听 CustomAutoComplete 组件的值变化,并手动更新 Form
    组件中的对应字段值。这种方法比较简单直接,但可能会导致父组件与 CustomAutoComplete 组件之间的耦合度增加。
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值