Javascript 角度1:选中大ng重复中的所有复选框

Javascript 角度1:选中大ng重复中的所有复选框,javascript,html,angularjs,checkbox,Javascript,Html,Angularjs,Checkbox,我有一个使用ng repeat创建的表,有数百行,最多600或700行。每行包括一个复选框,我在顶部有一个“全选”框,可以一次性选中所有复选框。然而,我遇到了浏览器性能问题,尤其是IE11(客户端首选)变得没有响应。几分钟后,所有复选框都显示为选中状态,但您仍然无法滚动或执行任何操作,因此它实际上是无用的 我已经创建了一个控制器数组,当单击复选框时,它会在模型(ng repeat中使用的模型)中循环,并向数组添加一个值。我认为是这种循环通过阵列导致了速度的减慢,但我不确定。分页已被排除,他们希望

我有一个使用ng repeat创建的表,有数百行,最多600或700行。每行包括一个复选框,我在顶部有一个“全选”框,可以一次性选中所有复选框。然而,我遇到了浏览器性能问题,尤其是IE11(客户端首选)变得没有响应。几分钟后,所有复选框都显示为选中状态,但您仍然无法滚动或执行任何操作,因此它实际上是无用的

我已经创建了一个控制器数组,当单击复选框时,它会在模型(ng repeat中使用的模型)中循环,并向数组添加一个值。我认为是这种循环通过阵列导致了速度的减慢,但我不确定。分页已被排除,他们希望所有行都在一页上

<table>
  <tbody>
    <tr>
      <th>Table Header</th>
      <th><input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" ng-change="vm.tickOrUntickAllCheckBoxes()" /> 
    </tr>
    <tr ng-repeat="payment in vm.payments>
      <td>{{ payment.somePaymentValue }}</td>
      <td>
          <input type="checkbox" class="paymentsApprovalCheckbox" 
              ng-checked="vm.approvedPayments.indexOf(payment.payId) > - 1"
              ng-value="payment.payId" ng-model="payment.approved" 
              ng-click="vm.handleCheckBoxClick(payment.payId)" /> 
      </td>
    </tr>
  </tbody>
</table>
将angular vm.tickOrUntickAllCheckBoxes()函数替换为一个普通的旧javascript选项会使checkAll框在IE11中几乎瞬间工作,但是我无法访问选中的payment.payId值。我想知道有没有人去拿?下面是纯javascript checkAll()函数:

<script>
    function checkAll(x) {
        var checkBoxes = document.getElementsByClassName('paymentsApprovalCheckbox');
        for (var i = 0; i < checkBoxes.length ; i++) {
            checkBoxes[i].checked = (x.checked == true);
        }
    }
</script>  

函数checkAll(x){
var checkbox=document.getElementsByClassName('paymentsaprovalcheckbox');
对于(变量i=0;i
然后我更新checkAll复选框,如下所示:

<input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" onclick="checkAll(this)" />

如果单独选中一个复选框,则会更新重复复选框中的ng model=“payment.approved”,但如果使用checkAll函数选中,则不会发生这种情况。angular是否可以检测使用checkAll()选中的框?我想这只是把过去不可避免的减速推迟到过程中稍晚的一点


有人有什么想法或解决办法吗?谢谢

我会尽量使用ng模型。在控制器中:

$onInit() {
  // If you need this from a REST call to populate, you'll have to
  // remember to do that here;
  this.model = {
    all: true,
    items: {}
  };
}
tickOrUntickAllCheckBoxes() {
  const boxes = this.model.items.length;
  this.model.all = !this.model.all;
  // Several ways to do this, forEach, map, etc.,
  this.model.items.forEach((item) => { item.checked = !this.model.all });
}
在您的循环中:

<tr>
  <th>Table Header</th>
  <th>
    <input type="checkbox"
      id="checkAllCheckBox"
      ng-model="vm.model.all"
      ng-change="vm.tickOrUntickAllCheckBoxes()" /> 
</tr>
<tr ng-repeat="payment in vm.payments track by $index">
  <td ng-bind="payment.somePaymentValue"></td>
  <td>
      <input type="checkbox"
        class="paymentsApprovalCheckbox" 
        ng-change="vm.approvedPayments($index)"
        ng-model="vm.model.items[$index]" /> 
  </td>
</tr>
对于单独设置,请执行以下操作:

approvedPayments(idx) {
  // Sets all the item's boxes checked, or unchecked;
  this.model.items[idx].checked = !this.model.items[idx].checked;

  // Possible call to extended model to get payment info; 
  handleCheckBoxClick(idx);
}
您应该能够将所有付款信息放入one approvedPayments()方法中,而不是有两个单独的方法(将逻辑移出模板并放入控制器或服务)。也就是说,您的模型可能看起来像:

this.model.items = [
  // One 'option' with id, payment etc;
  {
    id: 73,
    paymentId: 73,
    somePaymentValue: 210.73,
    currencyType: 'GBP',
    checked: false
  },
  {
    // Another 'option' etc...
  }
]

需要注意的一个问题是的不兼容,必须查找它(这就是为什么我没有在上面使用ng检查)。

感谢大家的建议。我提出的解决方案是将部分工作推回到服务器端。当页面加载时,我不再只是加载支付模型(其中每个支付记录包含大量信息),而是加载另外两个模型,其中一个是一组键/值对,其中键为payId,值均为false,另一个键相同,值均为true。例如:

{
     "1": false,
     "2": false
}
这些用于checkAll/uncheckall-只需将vm.approvedIDs变量设置为true或false即可。然后,vm.approvedIDs变量用作ng repeat复选框中的模型

当用户将ApprovedID发送回服务器以仅获取“true”条目的key/id时,我必须在服务器端做一些额外的工作。以下是相关的角度控制器功能:

$onInit() {
    // call http to get 'data' from server
    vm.payments = data.payments;
    vm.paymentIDsFalse = vm.approvedIDs = data.paymentIDsFalse;
    vm.paymentIDsTrue = data.paymentIDsTrue;
};

// tick/untick all boxes
vm.tickOrUntickAllCheckBoxes = function(){
    if (vm.allChecked == false) {
        vm.approvedPayments = vm.paymentIDsFalse;
    } else {
        vm.approvedPayments = vm.paymentIDsTrue;
    }
};

// tick/untick one box
vm.handleCheckBoxClick = function(payId, currentValue){
    vm.approvedPayments[payId] = currentValue;
};

vm.submitApprovedIds = function(){
    // post vm.approvedPayments to server 
};
HTML:


表头

这是Angular 1的缺陷之一。由于脏检查机制,它几乎会在数百条记录中为数百行中的每一行连续运行
indexOf()
函数。这意味着每次重画都要进行成千上万次的操作。不要运行
indexOf()。其思想是只渲染屏幕上的可见项,这样可以避免数百个不必要的绑定,而这些绑定可能会导致巨大的性能问题。在谷歌上搜索“angular virtual scroll”,你会发现一些可用的选项。
$onInit() {
    // call http to get 'data' from server
    vm.payments = data.payments;
    vm.paymentIDsFalse = vm.approvedIDs = data.paymentIDsFalse;
    vm.paymentIDsTrue = data.paymentIDsTrue;
};

// tick/untick all boxes
vm.tickOrUntickAllCheckBoxes = function(){
    if (vm.allChecked == false) {
        vm.approvedPayments = vm.paymentIDsFalse;
    } else {
        vm.approvedPayments = vm.paymentIDsTrue;
    }
};

// tick/untick one box
vm.handleCheckBoxClick = function(payId, currentValue){
    vm.approvedPayments[payId] = currentValue;
};

vm.submitApprovedIds = function(){
    // post vm.approvedPayments to server 
};
<table>
    <tbody>
        <tr>
            <th>Table Header</th>
            <th><input type="checkbox" id="checkAllCheckBox" ng-model="vm.allChecked" ng-change="vm.tickOrUntickAllCheckBoxes()"  /> 
        </tr>
        <tr ng-repeat="payment in vm.payments>
            <td>{{ payment.somePaymentValue }}</td>
            <td>
                <input type="checkbox" class="paymentsApprovalCheckbox"
                    ng-value="payment.payId"
                    ng-model="vm.approvedPayments[payment.payId]"
                    ng-click="vm.handleCheckBoxClick(payment.payId, vm.approvedPayments[payment.payId])" />
            </td>
        </tr>
    </tbody>
</table>