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

动态增删行表格中Autocomplete功能失效问题排查

动态表格行Autocomplete失效问题修复

问题根源

  1. 重复ID冲突:动态生成的输入框使用固定ID(如barcodeSearch),HTML中ID必须唯一,导致新行的Autocomplete无法正确绑定,且选择事件会错误修改第一行内容。
  2. HTML语法错误:动态生成的input标签存在未闭合、引号缺失问题,导致DOM结构异常。
  3. 初始行未初始化Autocomplete:默认第一行的输入框未绑定Autocomplete事件。
  4. 全局选择器错误:Autocomplete的select事件中使用全局ID选择器,无法定位当前行的对应输入框。

修复步骤及代码

1. 统一使用类选择器,移除重复ID

将所有动态元素的ID替换为类名,确保每行元素通过类名在当前行上下文查找。

2. 修正HTML语法错误

补全动态生成标签的引号和闭合部分。

3. 封装Autocomplete初始化函数

将Autocomplete的初始化逻辑封装成函数,方便初始行和新增行调用。

4. 调整select事件的元素定位

使用$(this).closest('tr')获取当前行,再通过类名查找该行内的输入框进行赋值。

修正后的完整代码

HTML部分

<table class="table table-bordered table-hover" id="tab_logic">
  <thead class="table-success">
    <tr>
      <th class="text-center">Barcode</th>
      <th class="text-center">Code</th>
      <th class="text-center">Stock In Hand</th>
      <th class="text-center">Stock Out Qty</th>
      <th class="text-center">Balance Qty</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <input class="form-control barcode-search" name="barcode[]" type="text" placeholder="Search By barcode" autocomplete="off">
      </td>
      <td>
        <input type="text" class="form-control product-name" readonly />
        <input type="hidden" class="form-control product-id" name="product_id[]" />
      </td>
      <td>
        <input type="number" class="form-control balance-qty" readonly />
      </td>
      <td>
        <input type="number" name="quantity[]" class="form-control stockout-qty balance-check" required />
      </td>
      <td>
        <div class="input-group">
          <input type="number" name="subTotal[]" class="form-control stock-balance" readonly />
          <div class="ibtnDel input-group-btn"> 
            <button class="btn btn-danger" type="button">
              <i class="fa fa-minus" aria-hidden="true"></i>
            </button>
          </div>
        </div>
      </td>
    </tr>
  </tbody>
</table>

<div class="col-md-12">
  <p class="pull-left">for new row press enter</p>
  <button id="add_row" class="btn btn-success pull-right"> 
    <i class="fa fa-plus" aria-hidden="true"></i> 
  </button>
</div>

<div class="col-md-12">
  <input class="btn btn-success pull-right" type="submit" value="Submit">
</div>

JavaScript部分

$(document).ready(function() {
  var counter = 0;

  // 封装Autocomplete初始化函数
  function initAutocomplete($input) {
    $input.autocomplete({
      source: function(request, response) {
        $.ajax({
          url: "{{route('getBarcodes')}}",
          type: 'post',
          dataType: "json",
          data: {
            _token: CSRF_TOKEN,
            search: request.term
          },
          success: function(data) {
            response(data);
          }
        });
      },
      select: function(event, ui) {
        var $row = $(this).closest('tr');
        // 给当前行的元素赋值
        $row.find('.barcode-search').val(ui.item.label);
        $row.find('.product-id').val(ui.item.product_id);
        $row.find('.product-name').val(ui.item.productCode);
        $row.find('.balance-qty').val(ui.item.balanceQty);
        return false;
      }
    });
  }

  // 初始化第一行的Autocomplete
  initAutocomplete($('.barcode-search'));

  $("#add_row").on("click", function(e) {
    e.preventDefault();
    var newRow = $("<tr>");
    var cols = "";

    // 修正HTML语法,使用类名代替ID
    cols += '<td><input type="text" placeholder="search by barcode" class="form-control barcode-search" name="barcode[]' + counter + '" /></td>';
    cols += '<td><input type="text" placeholder="Price" class="form-control product-name" name="product_code_' + counter + '" readonly/></td>';
    cols += '<input type="hidden" class="form-control product-id" name="product_id[]' + counter + '" />';
    cols += '<td><input type="number" placeholder="Stock In Hand" class="form-control balance-qty" name="balance_qty_' + counter + '" readonly/></td>';
    cols += '<td><input type="number" placeholder="Qty" class="form-control stockout-qty balance-check" name="quantity[]' + counter + '" /></td>';
    cols += '<td><div class="input-group"><input type="number" class="form-control stock-balance" name="subTotal[]' + counter + '" readonly/><div class="ibtnDel input-group-btn"> <button class="btn btn-danger" type="button"><i class="fa fa-minus" aria-hidden="true"></i></button></div></div></td>';

    newRow.append(cols);
    $("#tab_logic tbody").append(newRow);
    counter++;

    // 初始化新行的Autocomplete
    initAutocomplete(newRow.find('.barcode-search'));
  });

  $("#tab_logic tbody").on("click", ".ibtnDel", function(e) {
    e.preventDefault();
    $(this).closest("tr").remove();
    calc();
  });

  $('#tab_logic tbody').on('keyup change', '.stockout-qty', function() {
    calc();
  });

  function calc() {
    $('#tab_logic tbody tr').each(function(i, element) {
      var $row = $(this);
      var balanceQty = parseInt($row.find('.balance-qty').val()) || 0;
      var stockoutQty = parseInt($row.find('.stockout-qty').val()) || 0;
      $row.find('.stock-balance').val(balanceQty - stockoutQty);
      calc_total();
    });
  }

  function calc_total() {
    var totalBalance = 0;
    $('.stock-balance').each(function() {
      var val = parseInt($(this).val()) || 0;
      totalBalance += val;
    });
    // 可在此处添加总余额显示逻辑
  }

  $(document).on('keyup', '.balance-check', function() {
    var totalBalanceQty = 0;
    $('.balance-qty').each(function() {
      var val = parseInt($(this).val()) || 0;
      totalBalanceQty += val;
    });
    var $field = $(this);
    var balanceCheck = parseInt($field.val()) || 0;

    if (balanceCheck > totalBalanceQty) {
      swal({
        title: 'Excess Quantity Enter!',
        type: "warning",
        text: 'Your Enter QTY Greater than Available QTY.',
        timer: 5000
      }).then(
        function() {},
        function(dismiss) {
          if (dismiss === 'timer') {
            console.log('I was closed by the timer')
          }
        }
      );
      $field.val("");
    }
  });
});

关键修复点说明

  • 类代替ID:所有动态元素使用类名(如barcode-search、product-name),避免ID重复导致的选择器冲突。
  • 上下文查找:在select事件中通过closest('tr')获取当前行,再用类名查找该行内的元素,确保赋值正确对应到当前行。
  • 封装初始化函数:将Autocomplete逻辑封装,初始行和新增行统一调用,避免代码重复。
  • 修正语法错误:补全动态生成标签的引号和闭合,确保DOM结构正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:58:08