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

基于JSONForms实现联动下拉框(含API加载选项)的方案咨询

我来帮你搞定这个依赖下拉的需求,用JSON Forms实现完全没问题,尤其是需要从REST API拉取州数据的场景,我给你拆解成几个关键步骤:

1. 定义基础的JSON Schema与初始UISchema

首先得先把表单的数据结构和初始布局定下来,州字段默认设为只读:

1.1 JSON Schema(数据结构)

{
  "type": "object",
  "properties": {
    "country": {
      "type": "string",
      "enum": ["USA", "Canada", "Mexico"],
      "title": "国家"
    },
    "state": {
      "type": "string",
      "title": "州/省"
    }
  }
}

1.2 UISchema(布局与初始状态)

{
  "type": "VerticalLayout",
  "elements": [
    {
      "type": "Control",
      "scope": "#/properties/country"
    },
    {
      "type": "Control",
      "scope": "#/properties/state",
      "options": {
        "readonly": true
      }
    }
  ]
}
2. 实现依赖交互逻辑(React绑定为例)

JSON Forms的核心是自定义渲染器,我们可以给州字段写一个自定义控件,用来处理国家选择后的异步数据加载、状态切换和值清空逻辑。下面以React绑定(最常用的场景)为例:

2.1 创建自定义州下拉控件

import React, { useState, useEffect } from 'react';
import { useJsonFormsControl } from '@jsonforms/react';
import { Select, CircularProgress } from '@mui/material'; // 用Material UI举例,可替换为你用的UI库

const DependentStateSelect = () => {
  // 从JSON Forms获取表单数据、变更方法等核心属性
  const { data, handleChange, path } = useJsonFormsControl();
  const [stateOptions, setStateOptions] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isReadOnly, setIsReadOnly] = useState(true);

  // 监听国家字段的变化,触发后续逻辑
  useEffect(() => {
    const selectedCountry = data?.country;
    
    // 切换国家时先清空州的选中值和选项
    handleChange(path, undefined);
    setStateOptions([]);

    if (!selectedCountry) {
      setIsReadOnly(true);
      return;
    }

    // 选中国家后,开启可编辑状态并加载数据
    setIsReadOnly(false);
    setIsLoading(true);

    // 调用REST API获取对应国家的州数据
    fetch(`/api/states?country=${selectedCountry}`)
      .then(res => res.json())
      .then(states => {
        // 转换为JSON Forms下拉控件需要的选项格式
        const options = states.map(state => ({
          label: state.name,
          value: state.code
        }));
        setStateOptions(options);
      })
      .catch(err => console.error('加载州数据失败:', err))
      .finally(() => setIsLoading(false));
  }, [data?.country, handleChange, path]);

  return (
    <div style={{ position: 'relative' }}>
      <Select
        value={data?.state || ''}
        onChange={(e) => handleChange(path, e.target.value)}
        disabled={isReadOnly || isLoading}
        fullWidth
        displayEmpty
      >
        {stateOptions.map(opt => (
          <option key={opt.value} value={opt.value}>
            {opt.label}
          </option>
        ))}
      </Select>
      {/* 加载状态提示 */}
      {isLoading && (
        <CircularProgress
          size={20}
          style={{ position: 'absolute', right: 10, top: '50%', marginTop: -10 }}
        />
      )}
    </div>
  );
};

// 定义渲染器匹配规则:只匹配state字段的Control
export const dependentStateTester = (uischema, schema) => {
  return uischema.type === 'Control' && uischema.scope === '#/properties/state';
};

// 导出自定义渲染器
export const DependentStateRenderer = {
  tester: dependentStateTester,
  renderer: DependentStateSelect
};

2.2 在主组件中注册自定义渲染器

把自定义渲染器和JSON Forms自带的渲染器合并,传入表单组件:

import { JsonForms } from '@jsonforms/react';
import { materialRenderers } from '@jsonforms/material-renderers';
import { useState } from 'react';
import { DependentStateRenderer } from './DependentStateSelect';
import schema from './schema.json';
import uischema from './uischema.json';

const App = () => {
  const [formData, setFormData] = useState({});
  // 合并默认渲染器和自定义渲染器
  const renderers = [...materialRenderers, DependentStateRenderer];

  return (
    <JsonForms
      schema={schema}
      uischema={uischema}
      data={formData}
      renderers={renderers}
      onChange={({ data: newData }) => setFormData(newData)}
    />
  );
};

export default App;
3. 核心逻辑说明
  • 只读状态切换:未选择国家时保持只读,选中后自动解除只读
  • 值清空:每次切换国家时,通过handleChange(path, undefined)清空州的选中值
  • 异步数据加载:依赖useEffect监听国家字段变化,触发API请求并转换选项格式
  • 加载状态反馈:通过isLoading状态添加加载动画,提升用户体验
4. 其他绑定框架(Vue/Angular)的思路

如果用Vue或Angular绑定的JSON Forms,核心逻辑完全一致:

  1. 创建自定义组件,监听国家字段的变化
  2. 调用API获取州数据,更新组件的选项列表和禁用状态
  3. 将自定义组件注册到JSON Forms的渲染器列表中

比如Vue可以用@jsonforms/vue提供的useJsonFormsControl组合式API,写法和React版本大同小异。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:42:23