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

Laravel-admin中实现hasMany嵌套表单单选框互斥选中的问题

解决Laravel-admin hasMany嵌套表单中单选框全局互斥的问题

核心问题分析

Laravel-admin的hasMany组件会为每个嵌套表单的字段生成带索引的name属性(比如negotiations[0][comparative_statement]、negotiations[1][comparative_statement]),原生单选框的name互斥机制会失效,必须通过JavaScript主动控制所有相关单选框的选中状态。

可行解决方案

1. 修正JavaScript事件处理逻辑

替换原有脚本,使用以下代码实现全局单选框互斥:

protected function form() {
    Admin::script('
        // 事件委托到body,确保动态添加的嵌套表单也能触发事件
        $("body").on("change", "input[name*=\'negotiations\'][name*=\'comparative_statement\']", function() {
            // 取消所有同类型单选框的选中状态,除了当前点击的
            $("input[name*=\'negotiations\'][name*=\'comparative_statement\']").not(this).prop("checked", false);
        });

        // 页面加载时初始化状态,避免存在多个预选中的单选框
        $(document).ready(function() {
            const checkedRadios = $("input[name*=\'negotiations\'][name*=\'comparative_statement\']:checked");
            if (checkedRadios.length > 1) {
                checkedRadios.not(":first").prop("checked", false);
            }
        });
    ');

    $form->hasMany('negotiations', function (Form\NestedForm $form) {
        $form->radio('comparative_statement', __('Comparative Statement'))->options(['1' => 'yes']);
        $form->file('file')->rules('required');
        $form->text('vendor')->rules('required');
        $form->text('initial')->rules('required');
        $form->text('intermediate_1');
        $form->text('intermediate_2');
        $form->text('intermediate_3');
        $form->text('final_no_regret')->rules('required');
        $form->select('awarded')->options(['No' => 'No', 'Yes' => 'Yes'])->rules('required');
    });

    return $form;
}

2. 关键逻辑说明

  • 精准选择器:用input[name*='negotiations'][name*='comparative_statement']匹配所有嵌套表单中的目标单选框,避免误操作其他组件。
  • 动态事件绑定:事件委托到body,解决点击「添加」按钮生成的新表单无法触发事件的问题。
  • 初始状态修正:页面加载时检查并修正多选中的异常情况,保证初始状态符合要求。

3. 可选:后端存储优化

如果需要在后端明确记录哪一条negotiations被标记,可在主表新增selected_negotiation_id字段,同步更新该字段:

// 在form中添加隐藏字段
$form->hidden('selected_negotiation_id');

// 修改Admin::script逻辑
Admin::script('
    $("body").on("change", "input[name*=\'negotiations\'][name*=\'comparative_statement\']", function() {
        $("input[name*=\'negotiations\'][name*=\'comparative_statement\']").not(this).prop("checked", false);
        // 获取当前嵌套表单的记录ID(编辑状态)或索引(新增状态)
        const negotiationId = $(this).closest(".has-many-form").find("input[name*=\'id\']").val();
        $("input[name=\'selected_negotiation_id\']").val(negotiationId);
    });
');

之后在后端store/update方法中处理该字段的存储即可。

之前尝试无效的原因

  • 原有脚本仅在当前嵌套表单内取消选中,未覆盖全局所有单选框;
  • 选择器#has-many-negotiations input[type="radio"]匹配范围不准确,动态生成的DOM可能无法被捕获,属性包含选择器更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:13:23