mardi 24 octobre 2017

Angular 1: check all check boxes in a large ng-repeat

I have an table created using ng-repeat and there hundreds of rows, up to 600 or 700. Each row includes a checkbox and I have a "Check All" box at the top to check all the boxes in one go. However I'm running into browser performance issues, IE11 (the clients preferred choice) in particular becomes unresponsive. After several minutes all the checkboxes appear checked but you still can't scroll or do anything so it is effectively useless.

I have created a controller array and when the checkAll box is clicked it loops through the model (the one used in ng-repeat) and adds a value to the array. I presume it's this looping through the array that is causing the slow-down but I'm not sure. Pagination has been ruled out, they want all the rows on one page.

<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></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>

Here is the angular function that checks/unchecks all

vm.tickOrUntickAllCheckBoxes = function(){
    if (vm.allChecked == false) {
        vm.approvedPayments = [];
    } else {    
        vm.payments.forEach(function(payment){
            vm.approvedPayments.push(payment.payId);
        });
    }
};

Swapping out the angular vm.tickOrUntickAllCheckBoxes() function for a plain old javascript option makes the checkAll box work almost instantaneously in IE11 however I lose access to the checked payment.payId values. I wonder is there away for angular to get them? Here is the plain javascript checkAll() function:

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

Then I update the checkAll checkbox like this:

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

If you check one checkbox individually then the ng-model="payment.approved" in the repeating checkboxes is updated but this does not happen if they are checked with the checkAll function. Is it possible for angular to detect the boxes checked with checkAll()? I guess this is just putting off the same old inevitable slow-down to a slightly later point in the process.

Anyone have any ideas or work-arounds? Thanks!




Aucun commentaire:

Enregistrer un commentaire