You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在bpmn-io/form-js的文本类字段添加自动补全与提示框

解决方案:无需fork或新增字段,为form-js的textfield/textarea添加Tooltip与Autocomplete

核心思路

借助form-js的DOM渲染回调和自定义schema扩展,在表单渲染完成后,通过原生DOM操作或React组件挂载的方式,为目标字段增强Tooltip和Autocomplete功能,无需修改form-js源码。


一、Tooltip(提示框)实现

使用react-tooltip库,通过在schema中定义自定义tooltip配置,渲染完成后为对应字段绑定提示框。

import React, { useEffect, useRef } from 'react';
import { createForm } from '@bpmn-io/form-js';
import ReactTooltip from 'react-tooltip';

const MyForm = () => {
  const formContainer = useRef(null);

  useEffect(() => {
    const formSchema = {
      components: [
        {
          key: 'textField',
          label: '文本输入框',
          type: 'textfield',
          custom: {
            tooltip: '这是文本输入框的提示信息'
          }
        },
        {
          key: 'textArea',
          label: '文本域',
          type: 'textarea',
          custom: {
            tooltip: '这是文本域的提示信息'
          }
        }
      ]
    };

    const form = createForm({
      container: formContainer.current
    });

    // 导入表单 schema
    form.importSchema(formSchema).then(() => {
      // 表单渲染完成后,为字段绑定 tooltip
      formSchema.components.forEach(component => {
        if (component.custom?.tooltip) {
          // 找到对应字段的输入元素
          const inputElement = formContainer.current.querySelector(`[data-field-id="${component.key}"] input, [data-field-id="${component.key}"] textarea`);
          if (inputElement) {
            // 设置 react-tooltip 所需属性
            inputElement.setAttribute('data-tip', component.custom.tooltip);
            inputElement.setAttribute('data-for', 'form-tooltip');
          }
        }
      });
      // 重新初始化 tooltip
      ReactTooltip.rebuild();
    });

    return () => form.destroy();
  }, []);

  return (
    <div>
      <div ref={formContainer}></div>
      {/* 全局提示框容器 */}
      <ReactTooltip id="form-tooltip" place="top" effect="solid" />
    </div>
  );
};

export default MyForm;

关键说明

  • 在schema的custom字段中定义tooltip内容,作为自定义配置
  • 表单渲染完成后,通过data-field-id定位到目标输入元素
  • 为元素添加react-tooltip所需的data-tip和data-for属性,最后调用ReactTooltip.rebuild()生效

二、Autocomplete(自动补全)实现

使用react-autocomplete库,替换form-js原生的输入框,同时保持表单值的同步。

import React, { useEffect, useRef, useState } from 'react';
import { createForm } from '@bpmn-io/form-js';
import Autocomplete from 'react-autocomplete';
import ReactDOM from 'react-dom/client';

const MyForm = () => {
  const formContainer = useRef(null);
  // 自动补全选项
  const autocompleteOptions = [
    { label: '苹果', value: 'apple' },
    { label: '香蕉', value: 'banana' },
    { label: '樱桃', value: 'cherry' }
  ];

  useEffect(() => {
    const formSchema = {
      components: [
        {
          key: 'autoCompleteField',
          label: '带自动补全的输入框',
          type: 'textfield',
          custom: {
            autocomplete: true
          }
        }
      ]
    };

    const form = createForm({
      container: formContainer.current
    });

    form.importSchema(formSchema).then(() => {
      // 找到需要增强自动补全的字段容器
      const fieldContainer = formContainer.current.querySelector(`[data-field-id="autoCompleteField"]`);
      const nativeInput = fieldContainer.querySelector('input');
      if (fieldContainer && nativeInput) {
        // 隐藏原生输入框
        nativeInput.style.display = 'none';

        // 创建自动补全组件的挂载容器
        const autocompleteContainer = document.createElement('div');
        fieldContainer.appendChild(autocompleteContainer);

        // 获取当前字段的值
        const initialValue = form.getValue('autoCompleteField') || '';

        // 挂载自动补全组件
        const root = ReactDOM.createRoot(autocompleteContainer);
        root.render(
          <Autocomplete
            getItemValue={(item) => item.value}
            items={autocompleteOptions}
            renderItem={(item, isHighlighted) => (
              <div key={item.value} style={{ background: isHighlighted ? '#eee' : 'white', padding: '8px', cursor: 'pointer' }}>
                {item.label}
              </div>
            )}
            value={initialValue}
            onChange={(e) => {
              // 同步值到原生输入框和form实例
              nativeInput.value = e.target.value;
              form.setValue('autoCompleteField', e.target.value);
            }}
            onSelect={(val) => {
              form.setValue('autoCompleteField', val);
            }}
            // 自定义输入框渲染,保持和form-js一致的样式
            renderInput={(props) => (
              <input
                {...props}
                style={{
                  width: '100%',
                  padding: '8px',
                  border: '1px solid #ccc',
                  borderRadius: '4px'
                }}
              />
            )}
          />
        );
      }
    });

    return () => form.destroy();
  }, []);

  return (
    <div>
      <div ref={formContainer}></div>
    </div>
  );
};

export default MyForm;

关键说明

  • 在schema的custom字段中标记autocomplete: true,识别需要增强的字段
  • 表单渲染完成后,找到目标字段的容器,隐藏原生输入框
  • 创建新的容器挂载Autocomplete组件,通过form.setValue和form.getValue保持与form实例的值同步
  • 自定义输入框样式,匹配form-js的默认风格,保证UI一致性

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:39:55