代码之家  ›  专栏  ›  技术社区  ›  Chenomorfo

忽略下拉渲染选择项中的输入项-AntDesign

  •  1
  • Chenomorfo  · 技术社区  · 1 年前

    AntDesign表单

    我想使用“选择项目” a Custom Dropdown 渲染以显示预加载的数据,如果不存在,则可以添加新项。

    问题在于提交表单,因为下拉呈现有一个“输入项”,并且采用输入的值,而不是选择。

    Codepen of the code with the problem

    const DropdownCustom = () => {
      const [items, setItems] = useState(['jack', 'lucy']);
      const [name, setName] = useState('');
      const inputRef = useRef(null);
      const onNameChange = (event) => {
        setName(event.target.value);
      };
      const addItem = (e) => {
        e.preventDefault();
        setItems([...items, name || `New item ${index++}`]);
        setName('');
        setTimeout(() => {
          inputRef.current?.focus();
        }, 0);
      };
      return (
        <Select
          style={{
            width: 300,
          }}
          placeholder="custom dropdown render"
          dropdownRender={(menu) => (
            <>
              {menu}
              <Divider
                style={{
                  margin: '8px 0',
                }}
              />
              <Space
                style={{
                  padding: '0 8px 4px',
                }}
              >
                <Input              
                  placeholder="Please enter item"
                  ref={inputRef}
                  value={name}
                  onChange={onNameChange}
                  onKeyDown={(e) => e.stopPropagation()}
                />
                <Button type="text" icon={<PlusOutlined />} onClick={addItem}>
                  Add item
                </Button>
              </Space>
            </>
          )}
          options={items.map((item) => ({
            label: item,
            value: item,
          }))}
        />
      );
    };
    

    是否有方法设置输入以添加新数据并对选择项目的值进行优先级排序?

    2 回复  |  直到 1 年前
        1
  •  0
  •   Muhammad Nouman Rafique    1 年前

    当您将名称道具传递给Form.Item时,antd将克隆子项并将两个道具传递给子项 value onChange 。如果你可以通过在CustomDropdown中接受道具来验证并控制台它。你只需要将这些道具传递给<选择零部件以使其受控。您的输入与下拉列表无关。

    这是完整的代码。

    import { PlusOutlined } from '@ant-design/icons';
    import { Button, Checkbox, Divider, Form, Input, Select, Space } from 'antd';
    import { useRef, useState } from 'react';
    
    const DropdownCustom = (props) => {
        console.log(props); // => value, onChange
    
        const [items, setItems] = useState(['jack', 'lucy']);
        const [name, setName] = useState('');
        const inputRef = useRef(null);
        const onNameChange = (event) => {
            setName(event.target.value);
        };
        const addItem = (e) => {
            e.preventDefault();
            setItems([...items, name || `New item ${index++}`]);
            setName('');
            setTimeout(() => {
                inputRef.current?.focus();
            }, 0);
        };
        return (
            <Select
                {...props}
                style={{ width: 300 }}
                placeholder='custom dropdown render'
                dropdownRender={(menu) => (
                    <>
                        {menu}
                        <Divider style={{ margin: '8px 0' }} />
                        <Space style={{ padding: '0 8px 4px' }}>
                            <Input
                                placeholder='Please enter item'
                                ref={inputRef}
                                value={name}
                                onChange={onNameChange}
                                onKeyDown={(e) => e.stopPropagation()}
                            />
                            <Button type='text' icon={<PlusOutlined />} onClick={addItem}>
                                Add item
                            </Button>
                        </Space>
                    </>
                )}
                options={items.map((item) => ({ label: item, value: item }))}
            />
        );
    };
    
    const onFinish = (values) => {
        console.log('Success:', values);
    };
    const onFinishFailed = (errorInfo) => {
        console.log('Failed:', errorInfo);
    };
    
    const App = () => (
        <Form
            name='basic'
            labelCol={{ span: 8 }}
            wrapperCol={{ span: 16 }}
            style={{ maxWidth: 600 }}
            initialValues={{ remember: true }}
            onFinish={onFinish}
            onFinishFailed={onFinishFailed}
            autoComplete='off'
        >
            <Form.Item label='Username' name='username' rules={[{ required: true, message: 'Please input your username!' }]}>
                <Input />
            </Form.Item>
    
            <Form.Item label='Password' name='password' rules={[{ required: true, message: 'Please input your password!' }]}>
                <Input.Password />
            </Form.Item>
            <Form.Item label='Choose option' name='option' rules={[{ required: true, message: 'Please, choose an option' }]}>
                <DropdownCustom />
            </Form.Item>
            <Form.Item name='remember' valuePropName='checked' wrapperCol={{ offset: 8, span: 16 }}>
                <Checkbox>Remember me</Checkbox>
            </Form.Item>
    
            <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
                <Button type='primary' htmlType='submit'>
                    Submit
                </Button>
            </Form.Item>
        </Form>
    );
    

    您也可以按照antd-api获取更多示例。

    Why Form.Item not update value when children is nest?

        2
  •  0
  •   Chenomorfo    1 年前

    使用Form.useForm()

    我找到的一个解决方案是使用hookForm.useForm()

    //Add a prop to pass the onChangeEvent
    const DropdownCustom = ({onSelectChange = null}) => {
         //Custom code here....
      return (
        <Select
          //pass the prop directly to the Select component
          onChange={onSelectChange}
          style={{
            width: 300,
          }}
          placeholder="custom dropdown render"
          dropdownRender={(menu) => (
            <>
               {/*Any template of the dropdown you want*/}
            </>
          )}
          options={items.map((item) => ({
            label: item,
            value: item,
          }))}
        />
      );
    };
    
    const App = () => {
    //get the useForm hook
       const [form] = Form.useForm();
      //set manually the value 
        const handleSelectChange = (value) => {
        if (value) {
          form.setFieldsValue({ option: value });
        }
      };
    
        //Rest of your code here...
      
      return <Form
        {/*set the hook to the form*/}
        form={form}
        {/*more form props*/}>
        <Form.Item label="Choose option" name="option" rules={[{required:true,message:"Please, choose an option"}]}>
            <DropdownCustom onSelectChange={handleSelectChange}/>    
        </Form.Item>
         {/*Rest of the form body*/}
      </Form>
    };
    const ComponentDemo = App;
    
    createRoot(mountNode).render(<ComponentDemo />);
    
    

    You can try the new example here