Reputation: 1637
I am loading a main ng-repeat that has two nested ng-repeat's with a large dataset. The idea to show a parent record. The user can then tap on the parent record to see 2nd level details. The user can then tag again on the 2nd level to see further details. In total there are three ng-repeats.
When angular binds the data to the DOM elements, the screen is frozen for a couple of seconds.
I need to somehow solve this so that it doesn't freeze. I think my options are either paging or on-demand loading of the child repeats. The backend is a sqlite database.
Here is the plunkr http://embed.plnkr.co/NdipQQO2XiCGoIr00mGH/:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title></title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="ionic.css">
<script src="http://code.ionicframework.com/1.0.0-beta.11/js/ionic.bundle.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app='todo'>
<ion-pane>
<ion-content ng-controller="MyCtrl" padding="false" class="has-header">
<div class="bg-overlay"></div>
<div class="content-wrap">
<div class="container padding" style="background-color: #fff;" ng-show="gridData.length > 0">
<div class="row">
<div class="col col-75" style="font-weight: bold !important;">
Department / Product Type
</div>
<div class="col col-25" style="font-weight: bold !important;">
Qty
</div>
</div>
<div ng-repeat="item in gridData | orderBy:'-qty'" style="padding:0px;margin: 0;" ng-init="show = false">
<div class="row" ng-class-odd="'odd'" ng-class-even="'even'">
<div class="col col-75" style="padding:0;margin:0;" ng-click="show = !show">
{{item.departmentName}} - {{item.productTypeName}} (Click here)
</div>
<div class="col col-25" align="center" valign="middle" style="font-size: 14px;font-weight:bold;padding:0;margin:0;">
{{item.qty}}
</div>
</div>
<div ng-repeat="style in item.styles" style="padding:0;margin: 0;border: 1px solid #eee;" ng-show="show" ng-init="show2 = false">
<div class="row">
<div class="col" style="margin-left: 5% !important;border-top-width:0;border-bottom-width:0;" ng-click="show2 = !show2">
{{style.styleNum}} ({{style.qty}}) (Click here)
</div>
</div>
<div class="row" ng-show="show2">
<div class="col col-5" style="border:0"></div>
<div class="col col-5" style="border-left:0;border-bottom:0;border-right:0;"></div>
<div class="col col-25"><b>Color</b></div>
<div class="col col-15"><b>Size</b></div>
<div class="col"><b>Product#</b></div>
</div>
<div ng-repeat="styleLine in style.details" ng-show="show2">
<div class="row">
<div class="col col-10" style="border:0;"></div>
<div class="col col-25">{{styleLine.color}} ({{styleLine.qty}})</div>
<div class="col col-15">{{styleLine.size}}</div>
<div class="col">{{styleLine.productNum}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ion-content>
</ion-pane>
</body>
</html>
JS (I left the data part out, because its quite large to paste. It's in the plunkr available)
angular.module('todo', ['ionic'])
.controller('MyCtrl', function($scope) {
$scope.gridData = ...
});
The plunkr works fine without freezing the screen. But on my iPod it freezes and obviously this solutions will not scale well if I have 10.000 items.
How can I solve this by using paging or on-demand loading of the data when the user clicks on the header to see the child details, without rebinding the entire grid again? When using on-demand loading, I would preferably only get the details for that particular parent and somehow insert the ng-repeat dynamically, without having to re-load everything again. Hope that makes sense.
Upvotes: 1
Views: 898
Reputation: 2266
Angular creates watchers for you're expressions in the html, it is well known that over 2000 watxhers at a time has a very bad performance impact, I do not know how data you are using bit apparently you hit the 2000 mark, so we will need to reduce the amount of watchers you have. Let's start with replacing every ng-show you have to ng-if it should improve you're performance rapidlly, Secondly you should think if you can one-time bindings in you're code, one time binding is used like {{ :: expression }} It will not create a new watcher, and if you have some values you bind and they should not change on runtime you should use the one-time binding, Last but not least when you use ng-repeat always use 'track by $index' this has a huge performance impact if you're repeated list is interactive, you should read about it more in here - https://docs.angularjs.org/api/ng/directive/ngRepeat
Good luck!
Upvotes: 3