You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

react-admin中AutocompleteInput/AutocompleteArrayInput创建新选项方案问询

在react-admin中实现可创建新选项的Autocomplete组件

当然可以实现啦!react-admin本身并没有直接提供这个开箱即用的功能,但我们可以通过自定义组件或者拓展现有组件的方式,轻松复刻类似react-select的「Custom tag creation」效果——甚至能按照你提议的那样,把创建逻辑和数据适配器解耦,通过新增onCreate事件让你完全掌控后续的副作用处理。

核心需求拆解

先把咱们的需求捋清楚:

  • 用户输入时自动匹配现有标签选项
  • 输入内容无匹配项时,按下回车键触发新标签的创建流程
  • 创建成功后自动将新标签加入选项列表并选中
  • 解耦创建逻辑,允许用户自定义处理创建后的副作用(比如请求、状态更新等)

自定义拓展AutocompleteArrayInput组件

react-admin的自动完成组件底层基于react-select,所以我们可以直接借助react-select的Creatable组件来实现自定义创建功能,同时封装出支持onCreate事件的拓展组件。

完整代码示例

首先封装一个带创建能力的自定义组件:

import React, { useState } from 'react';
import { AutocompleteArrayInput, useDataProvider } from 'react-admin';
import { Creatable } from 'react-select/creatable';

const CreatableAutocompleteArrayInput = ({ onCreate, choices: initialChoices = [], ...props }) => {
    const dataProvider = useDataProvider();
    const [options, setOptions] = useState(initialChoices);

    // 处理标签创建逻辑
    const handleCreateOption = async (inputValue) => {
        let newItem = null;
        if (typeof onCreate === 'function') {
            // 优先使用用户自定义的创建逻辑
            newItem = await onCreate(inputValue);
        } else {
            // 默认创建逻辑:调用dataProvider创建新标签
            try {
                const response = await dataProvider.create('tags', {
                    data: { name: inputValue }
                });
                newItem = response.data;
            } catch (err) {
                console.error('创建标签失败:', err);
                return null;
            }
        }

        if (newItem) {
            // 将新创建的标签加入选项列表
            setOptions(prevOptions => [...prevOptions, newItem]);
        }
        return newItem;
    };

    return (
        <AutocompleteArrayInput
            {...props}
            choices={options}
            selectComponent={({ ...selectProps }) => (
                <Creatable
                    {...selectProps}
                    onCreateOption={handleCreateOption}
                    // 自定义创建选项的显示文案
                    formatCreateLabel={(value) => `创建新标签: "${value}"`}
                />
            )}
        />
    );
};

export default CreatableAutocompleteArrayInput;

在表单中使用这个组件

接下来在你的Customer创建表单里,就可以直接使用这个自定义组件了,还能按需传入自定义的onCreate逻辑:

import { Create, SimpleForm, TextInput, useDataProvider, useQuery } from 'react-admin';
import CreatableAutocompleteArrayInput from './CreatableAutocompleteArrayInput';

const CustomerCreate = () => {
    const dataProvider = useDataProvider();
    // 预先加载现有标签列表
    const { data: existingTags } = useQuery({
        queryKey: ['tags'],
        queryFn: () => dataProvider.getList('tags', { pagination: { page: 1, perPage: 100 }, sort: { field: 'name', order: 'ASC' } })
    });

    // 自定义创建逻辑示例(可选)
    const customCreateTag = async (inputValue) => {
        try {
            const response = await dataProvider.create('tags', {
                data: { name: inputValue }
            });
            console.log(`标签「${inputValue}」创建成功`);
            return response.data;
        } catch (err) {
            console.error('创建标签出错:', err);
            // 这里可以添加前端错误提示,比如用react-admin的notify函数
            return null;
        }
    };

    return (
        <Create title="创建客户">
            <SimpleForm>
                <TextInput source="name" label="客户名称" required />
                <CreatableAutocompleteArrayInput
                    source="tags"
                    label="客户标签"
                    choices={existingTags?.data || []}
                    onCreate={customCreateTag}
                    optionText="name"
                    optionValue="id"
                    placeholder="输入标签名称,按回车创建新标签"
                />
            </SimpleForm>
        </Create>
    );
};

export default CustomerCreate;

关键细节说明

  • 初始选项加载:用useQuery钩子预先获取现有标签列表,保证用户一开始就能看到可选择的选项
  • 解耦创建逻辑:如果不传入onCreate回调,组件会使用默认的dataProvider创建逻辑;传入自定义回调后,完全由你掌控创建流程(比如添加校验、埋点、错误提示等)
  • 自动选中新选项:react-select的Creatable组件会自动在创建完成后选中新选项,无需额外处理

内容的提问来源于stack exchange,提问作者Thanasis Ioannidis

火山引擎 最新活动