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

HTML OnChange与jQuery Append问题:动态表单新增行函数失效求助

问题解决:动态表单新增行的下拉框事件不生效

我开发的应用通过jQuery的append()实现动态表单,第一行的产品下拉框选中时能正常触发cargaLotes()函数加载对应批次数据,但通过append新增的行中,该函数完全无法生效。相关原代码如下:

</tr>            
<tr>
    <td>
        <select class="form-control" id="id_producto" name="id_producto[]" onchange="cargaLotes();">
            <option selected>Seleccione...</option>
            <?php
                foreach($data_productos as $dat3){
                    $id_producto = $dat3['id_producto'];
                    $desc_producto = $dat3['desc_producto_lab'];
            ?>
            <option value="<?php echo $id_producto; ?>">
                <?php echo $desc_producto; ?>
            </option>
            <?php }?>
        </select>
    </td>
    <td>
        <select class="form-control" id="id_lote" name="id_lote[]">
            <option>Seleccione...</option>
        </select>
    </td>
    <td><input type="text" id="num_lote" name="num_lote[]" class="form-control"></td>  
    <td><input type="date" id="fecha_vencimiento" name="fecha_vencimiento[]" class="form-control"></td>
    <td><button class="btn btn-primary addItemBtn" id="addItemBtn">(+)</button></td> 
</tr>
</table>
<center>
    <button type="submit" class="btn btn-success w-10" id="addCompra" name="addCompra">Registrar compra</button>
</center>
</div>
function cargaLotes(){
       
    $("#id_producto option:selected").each(function(){
        var id_producto = $(this).val();
        $.post("get_lotes.php",{id_producto:id_producto}, function(data){
            $("#id_lote").html(data);
        }); 
    });
}

$(document).ready(function(){
    var form_detalle = `
    <tr>
        <td>
            <select class="form-control" id="id_producto" name="id_producto[]" onchange="cargaLotes();">
                <option selected>Seleccione...</option>
                <?php
                    foreach($data_productos as $dat3){
                        $id_producto = $dat3['id_producto'];
                        $desc_producto = $dat3['desc_producto_lab'];
                ?>
                <option value="<?php echo $id_producto; ?>">
                    <?php echo $desc_producto; ?>
                </option>
            <?php }?>
            </select>
        </td>
        <td>
            <select class="form-control" id="id_lote" name="id_lote[]">
                <option>Seleccione...</option>
            </select>
        </td>
        <td><input type="text" id="num_lote" name="num_lote[]" class="form-control"></td>  
        <td><input type="date" id="fecha_vencimiento" name="fecha_vencimiento[]" class="form-control"></td>
        <td><button class="btn btn-danger removeItemBtn" id="removeItemBtn">(-)</button></td> 
    </tr> `;

    var max = 4; //MAXIMO DE FILAS DINAMICAS POR INSERTAR
    var x = 1;

    // FUNCION PARA AGREGAR LAS FILAS DINAMICAS
    $(".addItemBtn").click(function(e){
        e.preventDefault();
        if(x <= max){
            $("#tablaDetallesCompras").append(form_detalle);      
            x++;
        }     
    });

    // FUNCION PARA ELIMINAR LAS FILAS DINAMICAS AGREGADAS CON LA FUNCIÓN AGREGADA
    $("#tablaDetallesCompras").on('click', '.removeItemBtn', function(e){
        e.preventDefault();
        $(this).closest('tr').remove();
        x--;
    });
});

问题原因

  • 事件绑定失效:内联onchange="cargaLotes()"仅在页面初始化时绑定到已存在的元素,动态新增的元素不会自动继承该事件绑定。
  • ID重复冲突:所有行的下拉框都使用了相同的id="id_producto"和id="id_lote",HTML规范要求ID必须唯一,这会导致cargaLotes()中的选择器只会匹配第一个元素,即便事件能触发,也只会修改第一行的批次下拉框。

解决方案

步骤1:替换内联事件为事件委托

移除内联onchange属性,使用jQuery的事件委托机制,将事件绑定到静态父容器(如表格#tablaDetallesCompras),确保动态添加的元素也能触发事件。

步骤2:统一替换重复ID为Class

将所有重复的id属性改为class,避免ID冲突,同时方便通过当前元素定位同组控件。

步骤3:修改事件处理逻辑

基于触发事件的当前元素,定位到同一行的批次下拉框,确保每个产品下拉框仅修改对应行的批次选项。

修改后的完整代码

HTML初始行部分

<tr>
    <td>
        <select class="form-control id_producto" name="id_producto[]">
            <option selected>Seleccione...</option>
            <?php foreach($data_productos as $dat3): ?>
            <option value="<?php echo $dat3['id_producto']; ?>">
                <?php echo $dat3['desc_producto_lab']; ?>
            </option>
            <?php endforeach; ?>
        </select>
    </td>
    <td>
        <select class="form-control id_lote" name="id_lote[]">
            <option>Seleccione...</option>
        </select>
    </td>
    <td><input type="text" class="form-control num_lote" name="num_lote[]"></td>  
    <td><input type="date" class="form-control fecha_vencimiento" name="fecha_vencimiento[]"></td>
    <td><button class="btn btn-primary addItemBtn">(+)</button></td> 
</tr>

JavaScript部分

$(document).ready(function(){
    // 动态模板:替换ID为Class,移除内联onchange
    var form_detalle = `
    <tr>
        <td>
            <select class="form-control id_producto" name="id_producto[]">
                <option selected>Seleccione...</option>
                <?php foreach($data_productos as $dat3): ?>
                <option value="<?php echo $dat3['id_producto']; ?>">
                    <?php echo $dat3['desc_producto_lab']; ?>
                </option>
                <?php endforeach; ?>
            </select>
        </td>
        <td>
            <select class="form-control id_lote" name="id_lote[]">
                <option>Seleccione...</option>
            </select>
        </td>
        <td><input type="text" class="form-control num_lote" name="num_lote[]"></td>  
        <td><input type="date" class="form-control fecha_vencimiento" name="fecha_vencimiento[]"></td>
        <td><button class="btn btn-danger removeItemBtn">(-)</button></td> 
    </tr> `;

    var max = 4;
    var x = 1;

    // 添加行逻辑
    $(".addItemBtn").click(function(e){
        e.preventDefault();
        if(x <= max){
            $("#tablaDetallesCompras").append(form_detalle);      
            x++;
        }     
    });

    // 删除行逻辑
    $("#tablaDetallesCompras").on('click', '.removeItemBtn', function(e){
        e.preventDefault();
        $(this).closest('tr').remove();
        x--;
    });

    // 事件委托绑定产品下拉框change事件
    $("#tablaDetallesCompras").on('change', '.id_producto', function() {
        var id_producto = $(this).val();
        // 定位当前行的批次下拉框
        var $loteSelect = $(this).closest('tr').find('.id_lote');
        
        if(id_producto) {
            $.post("get_lotes.php", {id_producto: id_producto}, function(data){
                $loteSelect.html(data);
            });
        } else {
            // 选中默认选项时重置批次下拉框
            $loteSelect.html('<option>Seleccione...</option>');
        }
    });
});

关键修改说明

  • 移除内联事件,改用$("#tablaDetallesCompras").on('change', '.id_producto', ...)实现事件委托,覆盖静态和动态添加的元素。
  • 将重复ID替换为Class,符合HTML规范,同时让选择器能精准定位当前行的控件。
  • 事件处理函数中通过$(this)获取当前触发事件的下拉框,再用closest('tr')和find('.id_lote')找到对应批次下拉框,确保操作的是当前行的控件。
  • 增加了默认选项选中时重置批次下拉框的逻辑,优化用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:25:14