2017-10-24 7 views
0

ng-repeatを使用して作成されたテーブルが600または700までの数百の行にあります。各行にはチェックボックスがあり、 1つのボックス内のすべてのチェックボックスをオンにします。しかし、私はブラウザのパフォーマンスの問題にぶち当たっています。特にIE11(クライアントが選択したもの)は特に反応しなくなります。数分後にすべてのチェックボックスがチェックされているように見えますが、それでもスクロールしたり何もしないので効果的ではありません。角1:大規模なng-repeatのすべてのチェックボックスをチェック

コントローラアレイを作成しました。checkAllボックスをクリックすると、モデル(ng-repeatで使用されているもの)をループし、配列に値を追加します。私はそれが減速の原因となっているアレイを介してループしていると推測しますが、わかりません。改ページは除外されており、1ページにすべての行が必要です。ここで

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

はすべて

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

は、昔ながらのjavascriptオプションの角度vm.tickOrUntickAllCheckBoxes()関数は、しかし、IE11でほぼ瞬時checkAllボックスの作業を行いスワップアウト/チェックを解除を確認し、角度の関数であります私は、確認された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チェックボックス更新:あなたは個別に1つのチェックボックスをチェックすると

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

をその後、NG-モデルは= "payment.approved"繰り返すチェックボックスの中のチェックボックスは更新されますが、checkAll関数でチェックされている場合は発生しません。 checkAll()でチェックしたボックスを角度で検出することは可能ですか?私はこれが、ちょっと遅れて、同じ年を必然的に遅くすることをやめていると思う。

誰でも任意のアイデアや回避策がありますか?ありがとう!

+1

これは角度1の脆弱性の1つです。汚れたチェックメカニズムのため、何百行ものレコードごとに何百ものレコードの中で 'indexOf()'関数をほぼ連続して実行します。それはそれぞれの再塗装のための数十万の操作です。 'indexOf()'を実行する代わりに、 'indexOf()'の結果をキャッシュして一度だけ実行するような真偽値をどこかに格納する方法を見つけるべきです。 –

+1

私は過去に "仮想"リストを使ってAngular 1の大きなリストパフォーマンスの問題を解決しました。考えられるのは、画面上の目に見えるアイテムだけがレンダリングされるため、膨大なパフォーマンス上の問題を引き起こす可能性のある何百もの不要なバインディングが節約できます。 "角の仮想スクロール"のためのGoogleの検索を行い、あなたはいくつかのオプションを見つけることができます。 – james00794

答えて

1

私はその能力の中で最高のngモデルを使用します。お使いのコントローラで次に

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

:あなたのループでは

$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 }); 
} 

そして個別に設定する:

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); 
} 

あなたはする必要がありますすべての支払い通知を置くことができるテンプレートからロジックをコントローラまたはサービスに移動する2つの別個のメソッドを持たずに、1つのapprovedPayments()メソッドに追加します。つまり、あなたのモデルは次のようになります。注意すべき

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

1つの問題は、ngChecked with ngModelの非互換性である、(私はNG-確認上記で使用していない理由である)それを見ていました。

0

ご意見ありがとうございました。私が思いついた解決策は、仕事の一部をサーバー側に戻すことでした。ペイメントモデルを読み込む代わりに(各ペイメントレコードには多くの情報が含まれています)、ページが読み込まれるときに2つの追加モデルが読み込まれます。その1つは、キーが支払われるキーと値のペアのセットで、すべてが偽であり、同じキーを持ち、すべての値が真である別のものです。例:

{ 
    "1": false, 
    "2": false 
} 

これらはcheckAll/Uncheck allに使用されます。vm.approvedIDs変数をtrueまたはfalseに設定するだけです。次に、vm.approvedIDs変数がng-repeatチェックボックスのモデルとして使用されます。

ユーザーが「実際の」エントリのキー/ IDのみを取得するために、承認済みの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:これらの追加モデルを作成するよりも良い方法がなければならないかのように

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

それは私には見えますが、それは今のためにかなりスムーズに働いています私は次のものに進むことができます!

関連する問題