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

AngularJS中如何在表格ng-change事件后保持输入框焦点?

问题:AngularJS表格修改数量后输入框丢失焦点

我碰到个麻烦事儿:当修改表格里商品数量的输入框值时,触发ng-change事件后,输入框会立刻失去焦点,没法连续输入数字。

(场景说明:表格中的数量输入框在输入数值后,焦点自动离开输入框,无法继续输入)

相关代码

AngularJS 控制器的ng-change逻辑

$scope.txtqty = function (item) { 
  var id = item.Id; 
  $http.put("/api/Products/txtqty/" + id, item)
    .then(function (response) { 
      $scope.gridproducts = response.data; 
    }) 
}

HTML表格代码

<tbody> 
  <tr ng-repeat="item in gridproducts"> 
    <td ng-click="griddelete(item.Id)"><a class="delete"><i class="fa fa-times-circle-o"></i></a></td> 
    <td class="name">{{item.ProductName}}</td> 
    <td>{{item.ProductRate}}</td> 
    <td><input class="form-control qty" type="text" style="width:50px" ng-change="txtqty(item)" ng-model="item.ProductQty" value="{{item.ProductQty}}"></td> 
    <td>{{item.TotalAmount}}</td> 
  </tr> 
  <tr></tr> 
  <tfoot>
    <tr>
      <th colspan="2"></th>
      <th colspan="2"><b>Total</b></th>
      <th><b>{{gridproducts[0].TotalBill}}</b></th>
    </tr>
    <tr>
      <th colspan="2"><b></b></th>
      <th colspan="2"><b>Total Items</b></th>
      <th><b>25</b></th>
    </tr>
  </tfoot> 
</table>

问题根源

为啥会这样呢?核心原因是你替换了整个gridproducts数组:每次请求后端成功后,你直接把响应数据赋值给$scope.gridproducts,AngularJS检测到数组引用变化,就会重新渲染整个ng-repeat列表。原来的输入框是列表里的一个DOM元素,重新渲染后这个元素被销毁再重建,焦点自然就丢失了。

最优解决方案:局部更新数据,而非替换整个数组

不需要把整个数组换掉,只需要更新被修改的那一项数据就行。这样ng-repeat只会更新对应的行,不会动其他DOM元素,输入框的焦点就能稳稳保留。

修改后的控制器代码:

$scope.txtqty = function (item) { 
  var id = item.Id; 
  $http.put("/api/Products/txtqty/" + id, item)
    .then(function (response) { 
      // 从响应数据里找到修改后的那一项
      const updatedItem = response.data.find(product => product.Id === id);
      if (updatedItem) {
        // 找到原数组中对应项的位置,替换它
        const targetIndex = $scope.gridproducts.findIndex(product => product.Id === id);
        $scope.gridproducts[targetIndex] = updatedItem;
        
        // 如果需要更新汇总的TotalBill,单独更新(因为它在数组第一项)
        if ($scope.gridproducts[0]) {
          $scope.gridproducts[0].TotalBill = response.data[0].TotalBill;
        }
      }
    }) 
}

另外,HTML输入框里的value="{{item.ProductQty}}"是多余的——ng-model已经负责数据绑定了,重复写反而可能引发冲突,建议删掉:

<td><input class="form-control qty" type="text" style="width:50px" ng-change="txtqty(item)" ng-model="item.ProductQty"></td>

备选方案:手动恢复焦点(迫不得已时用)

如果因为后端返回结构限制,必须替换整个数组,那可以在DOM重新渲染后手动把焦点切回去。步骤如下:

  1. 给输入框加一个唯一ID:
<td><input id="qty-input-{{item.Id}}" class="form-control qty" type="text" style="width:50px" ng-change="txtqty(item)" ng-model="item.ProductQty"></td>
  1. 修改控制器代码,用$timeout等待DOM渲染完成后恢复焦点(记得给控制器注入$timeout服务):
$scope.txtqty = function (item) { 
  var id = item.Id; 
  // 先记下当前输入框的ID
  const targetInputId = `qty-input-${id}`;
  
  $http.put("/api/Products/txtqty/" + id, item)
    .then(function (response) { 
      $scope.gridproducts = response.data; 
      // 用$timeout让AngularJS先完成DOM更新,再获取焦点
      $timeout(() => {
        document.getElementById(targetInputId).focus();
      });
    }) 
}

不过还是优先用第一种局部更新的方案,它不仅能解决焦点问题,还减少了不必要的DOM渲染,性能更好,也更符合AngularJS的数据绑定思路。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:22:27