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

如何在Formio自定义组件中实例化多个基础Select组件?

复用Formio原生Select组件实现多选择组自定义组件

要在自定义组件里保留Formio Select的完整逻辑(包括多选),核心是直接实例化Formio原生的Select组件,而不是手动渲染下拉框。以下是具体实现方案:

核心思路

自定义组件继承Formio的基础Component类,在组件生命周期中动态创建并挂载多个原生Select组件实例,通过事件监听实现父子组件的数据同步,从而完全复用Select的所有内置功能。

完整代码示例

import { components } from 'formiojs';

// 定义自定义多选择组组件
class MultiSelectGroupComponent extends components.components.base.Component {
  constructor(component, options, data) {
    super(component, options, data);
    // 可通过组件配置动态传入,这里先硬编码示例配置
    this.childSelectConfigs = this.component.childSelects || [
      {
        key: 'dayPart',
        label: '时段',
        multiple: true,
        data: { values: [{ label: '上午', value: 'am' }, { label: '下午', value: 'pm' }, { label: '晚上', value: 'night' }] }
      },
      {
        key: 'weekDay',
        label: '星期',
        multiple: true,
        data: { values: [{ label: '周一', value: '1' }, { label: '周二', value: '2' }, { label: '周三', value: '3' }] }
      },
      {
        key: 'month',
        label: '月份',
        multiple: true,
        data: { values: [{ label: '一月', value: '1' }, { label: '二月', value: '2' }, { label: '三月', value: '3' }] }
      }
    ];
    this.childComponents = [];
  }

  async init() {
    await super.init();
    // 逐个创建并挂载原生Select组件
    for (const config of this.childSelectConfigs) {
      // 原生Select组件类
      const SelectComponent = components.components.select;
      // 实例化子组件,传递父组件的配置、选项和数据上下文
      const child = new SelectComponent({ type: 'select', ...config }, this.options, this.data);
      
      await child.init();
      // 将子组件DOM挂载到自定义组件容器
      this.element.appendChild(child.element);
      // 监听子组件值变化,同步到父组件
      child.on('change', () => this.syncParentValue());
      
      this.childComponents.push(child);
    }
    // 初始化父组件值
    this.syncParentValue();
  }

  // 同步子组件值到父组件
  syncParentValue() {
    this.value = this.childComponents.reduce((acc, child) => {
      acc[child.component.key] = child.value;
      return acc;
    }, {});
    this.emit('change', this.value);
  }

  // 父组件值变化时同步到子组件
  setValue(value) {
    super.setValue(value);
    if (!value) return;
    this.childComponents.forEach(child => {
      if (value[child.component.key] !== undefined) {
        child.setValue(value[child.component.key]);
      }
    });
  }

  // 渲染自定义组件容器
  render() {
    this.element = super.render('div', { class: 'multi-select-group d-flex gap-3' });
    return this.element;
  }
}

// 注册自定义组件到Formio组件库
components.addComponent('multiSelectGroup', MultiSelectGroupComponent);

关键细节说明

  1. 组件继承与生命周期:继承Formio的base.Component,确保和原生组件生命周期一致,避免出现渲染或数据同步问题。
  2. 原生Select实例化:直接使用components.components.select获取原生Select组件类,传入配置、上下文参数实例化,完整复用多选、搜索、选项过滤等功能。
  3. 数据同步:通过change事件监听子组件值变化,实时更新父组件的value;父组件setValue时反向同步到子组件,保证数据一致性。
  4. 可配置化扩展:如果需要在Formio编辑器中让用户自定义子Select的选项、标签等,可以在自定义组件的schema中添加childSelects配置字段,替换代码中的硬编码配置。

使用方式

注册组件后,在Formio编辑器中就能找到multiSelectGroup组件,添加到表单后即可使用,其提交数据结构为:

{
  "multiSelectGroup": {
    "dayPart": ["am", "pm"],
    "weekDay": ["1"],
    "month": ["2", "3"]
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:50:26