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

Chosen插件在HTML表格动态生成行中失效问题求助

Chosen插件动态克隆行下拉失效问题解决

我用Chosen插件实现表格首行的下拉筛选功能,正常工作。但动态克隆生成新行后,下拉列表失效,且所有新行都显示首行的选中值。相关代码如下:

原HTML代码

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Medicine Re-Location Form</title>    
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> 
    <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.jquery.min.js"></script>
    <link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/chosen/1.8.7/chosen.min.css">
</head>
<body>
<div class="container">
  <div class="card">
    <h3 div class="card-header" style="background-color: #3fbbc0;">Request Form</h3>
    <div class="card-body">
    <form method="POST" action="invoice.php">
              <table class="table table-bordered">
                    <thead class="table-success" style="background-color: #3fbbc0;">
                    <tr>                       
                        <th width="15%"><center>Product</th>                       
            <th width="10%"><center>Qty (No)</th>                   
            <th width="20%"><center>Remarks</th>
            <th width="5%"></th>                                               
                         <button type="button" class="btn btn-sm btn-success" onclick="BtnAdd()">Add Item</button>                         
                        </th>
</tr>
                    </thead>
                    <tbody id="TBody">
                      <tr id="TRow" >
<td><Select  class="scode form-control text-end" name="scode[]" id = "scode"  class="form-control"  required onchange="GetDetail(this.closest('tr'))">
<option value="">Select Product</option>
    <?php
    include('db.php');
    $sql = mysqli_query($con,"SELECT * FROM procd2");
    while($row=mysqli_fetch_array($sql))
    {
    echo '<option value="'.$row['pro1'].'">'.$row['pro1'].'</option>';
    } ?></select>
</td>       
        <td><input type="text" class="qty form-control text-end" name="qty[]" id="ccc" pattern="\d+"></td>    
       
           <td><input type="text" class="form-control text-end" name="remarks3[]"  id="zzz" ></td>
        <td class="NoPrint"><button type="button" class="btn btn-success"  style="line-height: 1;" onclick="BtnDel(this)">x</button></td>
            
                      </tr>   </tbody> </table>

<script>
jQuery('.scode').chosen();
</script>

 <div class="col-lg-4"> <div class="form-group"><center>
        <input type="submit" name="submit" id="submit" value="Submit"  class="btn btn-success submit_btn invoice-save-btm">     
</form> 

原JavaScript代码

function GetPrint()
{
    /*For Print*/
    window.print();
}

function BtnAdd()
{
    /*Add Button*/
    var v = $("#TRow").clone().appendTo("#TBody") ;
    $(v).find("input").val('');
$(v).find("select.scode").chosen();
   
    $(v).removeClass("d-none");
    $(v).find("th").first().html($('#TBody tr').length - 1);
}

function BtnDel(v)
{
    /*Delete Button*/
       $(v).parent().parent().remove(); 
       GetTotal();

        $("#TBody").find("tr").each(
        function(index)
        {
           $(this).find("th").first().html(index);
        }

       );
}

function Calc(v)
{
    /*Detail Calculation Each Row*/
    var index = $(v).parent().parent().index();
    
    var qqq1 = document.getElementsByName("qty[]")[index].value;

    GetTotal();
}

function GetTotal()
{
    /*Footer Calculation*/   
    var sum=0;
    var amts =  document.getElementsByName("tot4[]");

    for (let index = 0; index < amts.length; index++)
    {
        var tot4 = amts[index].value;
        sum = +(sum) +  +(tot4) ; 
    }

    document.getElementById("totbil").value = sum;

    var gst =  document.getElementById("adv11").value;
    var net = +(sum) - +(gst);
    document.getElementById("netpayable1").value = net;
}

问题原因分析

  • 模板行的表单元素带有固定ID(如scode、ccc),克隆后出现重复ID,引发DOM冲突;
  • 直接克隆已初始化Chosen的DOM元素,会携带原选中状态和Chosen生成的额外结构,导致新行继承旧状态;
  • 初始化新行Chosen时,未清理原实例,造成绑定异常。

解决方案

1. 修改HTML模板行

移除所有重复ID,改用类选择器标记模板行:

<tbody id="TBody">
  <tr class="TRow"> <!-- 将ID改为类 -->
    <td>
      <!-- 移除id="scode",保留类名scode -->
      <select class="scode form-control text-end" name="scode[]" required onchange="GetDetail(this.closest('tr'))">
        <option value="">Select Product</option>
        <?php
        include('db.php');
        $sql = mysqli_query($con,"SELECT * FROM procd2");
        while($row=mysqli_fetch_array($sql))
        {
        echo '<option value="'.$row['pro1'].'">'.$row['pro1'].'</option>';
        } ?>
      </select>
    </td>       
    <td>
      <!-- 移除id="ccc" -->
      <input type="text" class="qty form-control text-end" name="qty[]" pattern="\d+">
    </td>    
    <td>
      <!-- 移除id="zzz" -->
      <input type="text" class="form-control text-end" name="remarks3[]">
    </td>
    <td class="NoPrint">
      <button type="button" class="btn btn-success" style="line-height: 1;" onclick="BtnDel(this)">x</button>
    </td>
  </tr>
</tbody>

2. 修改BtnAdd函数

克隆前销毁模板行的Chosen实例,重置新行表单状态,再重新初始化:

function BtnAdd() {
    // 获取模板行并克隆
    var templateRow = $(".TRow").first().clone();
    // 销毁模板行的Chosen实例,恢复原生select
    $(".TRow .scode").chosen('destroy');
    // 清空新行input值
    templateRow.find("input").val('');
    // 重置新行select为默认选项
    templateRow.find("select.scode").val('').prop('selectedIndex', 0);
    // 将新行添加到表格
    templateRow.appendTo("#TBody");
    // 重新初始化模板行的Chosen
    $(".TRow .scode").chosen();
    // 初始化新行的Chosen
    templateRow.find("select.scode").chosen();
    // 更新行号(如果需要)
    templateRow.find("th").first().html($('#TBody tr').length - 1);
}

说明

  • 销毁模板行的Chosen是为了确保克隆的是原生select,避免携带旧状态;
  • 移除重复ID可避免DOM操作时的冲突问题;
  • 重置select选中值保证新行默认显示“Select Product”选项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 03:45:54