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
相关产品推荐
相关产品推荐

