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

如何实现父子关系Select Box的动态绑定

动态绑定父子关系下拉框问题

需求说明

  • 页面加载时显示「Program Type」下拉框,选项为Type A和Type B
  • 选择Type A后,生成其子选项对应的下拉框(No of Days、color of the car),以此类推完成层级展开
  • 页面末尾的按钮需在所有子下拉框都选择到无后代的选项后激活

现有数据源

var jsonData = [{
            "id": 1,
            "title": "Program Type",
            "field_value": "Select program type",
            "type_id": "1",
            "width": "500",
            "height": "500",
            "children": [{
                "id": "2",
                "title": "Type A",
                "field_value": "Type A",
                "type_id": "1",
                "width": "500",
                "height": "500",
                "children": [{
                    "id": "4",
                    "title": "No of Days",
                    "field_value": "No of Days",
                    "type_id": "1",
                    "width": "500",
                    "height": "500",
                    "children": [{
                        "id": "6",
                        "title": "3 Days",
                        "field_value": "3 Days",
                        "type_id": "1",
                        "width": "500",
                        "height": "500",
                        "children": []
                    }, {
                        "id": "7",
                        "title": "2 Days",
                        "field_value": "2 Days",
                        "type_id": "1",
                        "width": "500",
                        "height": "500",
                        "children": []
                    }]
                }, {
                    "id": "5",
                    "title": "color of the car",
                    "field_value": "color of the car",
                    "type_id": "1",
                    "width": "500",
                    "height": "500",
                    "children": [{
                        "id": "8",
                        "title": "Red",
                        "field_value": "Red",
                        "type_id": "1",
                        "width": "500",
                        "height": "500",
                        "children": []
                    }, {
                        "id": "9",
                        "title": "Black",
                        "field_value": "Black",
                        "type_id": "1",
                        "width": "500",
                        "height": "500",
                        "children": []
                    }]
                }]
            }, {
                "id": "3",
                "title": "Type B",
                "field_value": "Type B",
                "type_id": "1",
                "width": "500",
                "height": "500",
                "children": [{
                    "id": "10",
                    "title": "typ b child a",
                    "field_value": "typ b child a",
                    "type_id": "1",
                    "width": "500",
                    "height": "500",
                    "children": []
                }, {
                    "id": "11",
                    "title": "typ b child b",
                    "field_value": "typ b child b",
                    "type_id": "1",
                    "width": "500",
                    "height": "500",
                    "children": []
                }]
            }]
        }];

尝试的代码(存在问题)

var jsonData = <?php echo json_encode($allData); ?>;
let displayObj = '';
jsonData.forEach(function (rootObject) {
    displayObj += '<div class="row">';
    displayObj += '<div class="col-md-6">';
    displayObj += '<label for="inputEmail4" class="form-label"> '+rootObject.title+' </label>';
    displayObj += '<select id="'+rootObject.title.toLowerCase().replace(' ', '_')+'" class="form-select" onchange="handleSelectChange(this)">';

    displayObj += '<option value="0"> '+rootObject.field_value+' </option>';

    rootObject.children.forEach(function (childObj){
        displayObj += '<option value="'+childObj.field_value+'"> '+childObj.field_value+' </option>';
    });

    displayObj += '</select>';
    displayObj += '</div>';
    displayObj += '</div>';
});

$('#select-container').html(displayObj);
function renderOptions(options, parentId) {
    var select = $('<select>', {
        id: parentId,
        class: 'form-select',
        onchange: 'handleSelectChange(this)'
    });

    select.append('<option value="">Select an option</option>');

    options.forEach(function (option) {
        select.append('<option value="' + option.id + '"> ' + option.title + '</option>');
    });
    $('#select-container').append(select);
}
function handleSelectChange(select) {
    var selectedValue = $(select).val();
    console.log('Selected value:', selectedValue);

    // Remove existing child select boxes
    $(select).nextAll('select').remove();

    // Check if the selected option has children
    var selectedOption = jsonData.find(obj => obj.id == selectedValue);
    if (selectedOption && selectedOption.children && selectedOption.children.length > 0) {
        // Create and append a new select box for each child
        renderOptions(selectedOption.children, selectedOption.title.toLowerCase().replace(' ', '_'));
    }
}

问题分析与修正方案

原代码核心问题:

  1. 无法查找嵌套子节点:jsonData.find仅能遍历顶层节点,无法定位深层子节点
  2. 渲染逻辑错误:选中Type A后需同时渲染两个子下拉框,原代码仅生成一个
  3. 缺少按钮激活判断逻辑:未实现检查所有层级是否选择完成的逻辑

修正后的完整代码

<div id="select-container"></div>
<button id="submit-btn" disabled>提交</button>
// 递归查找对应ID的节点
function findNodeById(nodes, id) {
    for (let node of nodes) {
        if (node.id == id) return node;
        if (node.children && node.children.length > 0) {
            let found = findNodeById(node.children, id);
            if (found) return found;
        }
    }
    return null;
}

// 渲染单个下拉框组(包含label和布局结构)
function renderSelectGroup(node, container) {
    const row = $('<div class="row mb-3"></div>');
    const col = $('<div class="col-md-6"></div>');
    const label = $(`<label class="form-label">${node.title}</label>`);
    const selectId = node.title.toLowerCase().replace(' ', '_');
    const select = $(`<select id="${selectId}" class="form-select"></select>`);
    
    // 添加默认提示选项
    select.append(`<option value="">${node.field_value}</option>`);
    
    // 添加子选项
    node.children.forEach(child => {
        select.append(`<option value="${child.id}">${child.title}</option>`);
    });
    
    // 绑定选择事件
    select.on('change', function() {
        handleSelectChange(this, container);
    });
    
    col.append(label).append(select);
    row.append(col);
    container.append(row);
}

// 处理下拉框选择事件
function handleSelectChange(select, container) {
    const selectedId = $(select).val();
    const $selectRow = $(select).closest('.row');
    
    // 移除当前下拉框之后的所有层级下拉框
    $selectRow.nextAll('.row').remove();
    
    if (!selectedId) {
        checkSubmitStatus();
        return;
    }
    
    // 查找选中的节点
    const selectedNode = findNodeById(jsonData, selectedId);
    if (!selectedNode) return;
    
    // 渲染所有子下拉框组
    if (selectedNode.children && selectedNode.children.length > 0) {
        selectedNode.children.forEach(child => {
            renderSelectGroup(child, container);
        });
    }
    
    checkSubmitStatus();
}

// 检查是否所有下拉框都选择到无后代的选项,控制按钮状态
function checkSubmitStatus() {
    const selects = $('#select-container .form-select');
    let allCompleted = true;
    
    for (let i = 0; i < selects.length; i++) {
        const select = selects[i];
        const selectedId = $(select).val();
        if (!selectedId) {
            allCompleted = false;
            break;
        }
        const node = findNodeById(jsonData, selectedId);
        if (node.children && node.children.length > 0) {
            allCompleted = false;
            break;
        }
    }
    
    $('#submit-btn').prop('disabled', !allCompleted);
}

// 页面初始化
$(document).ready(function() {
    const container = $('#select-container');
    jsonData.forEach(root => {
        renderSelectGroup(root, container);
    });
    checkSubmitStatus();
});

修正要点说明

  • 递归节点查找:新增findNodeById函数,遍历所有层级节点定位目标项
  • 结构化渲染:每个下拉框包含label和标准布局结构,保持页面样式统一
  • 层级清理:选中选项后移除当前下拉框之后的所有层级,避免残留旧组件
  • 按钮激活逻辑:checkSubmitStatus函数检查所有下拉框是否都选择到无后代的选项,满足条件则启用提交按钮

内容的提问来源于stack exchange,提问作者Randheer Singh Chouhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:08:11