In a performance purpose, i wanted to remove the double data-binding (so, the associated watchers) from my ng-repeat.
It loads 30 items, and those data are static once loaded, so no need for double data binding.
The thing is that the watcher amount remains the same on that page, no matter how i do it.
Let say :
<div ng-repeat='stuff in stuffs'>
// nothing in here
</div>
Watchers amount is 211 (there is other binding on that page, not only ng-repeat)
<div ng-repeat='stuff in ::stuffs'>
// nothing in here
</div>
Watchers amount is still 211 ( it should be 210 if i understand it right), but wait :
<div ng-repeat='stuff in ::stuffs'>
{{stuff.id}}
</div>
Watchers amount is now 241 (well ok, 211 watchers + 30 stuffs * 1 watcher = 241 watchers)
<div ng-repeat='stuff in ::stuffs'>
{{::stuff.id}}
</div>
Watchers amount is still 241 !!! Is :: not supposed to remove associated watcher ??
<div ng-repeat='stuff in ::stuffs'>
{{stuff.id}} {{stuff.name}} {{stuff.desc}}
</div>
Still 241...
Those exemples has really been made in my app, so those numbers are real too.
The real ng-repeat is far more complex than the exemple one here, and i reach ~1500 watchers on my page. If i delete its content ( like in the exemple), i fall down to ~200 watchers. So how can i optimize it ? Why :: does't seem to work ?
Thank you to enlighten me...
You can consider using transclusion inside a custom directive, to achieve the behavior you are looking for without using ng-repeat.
Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.
$first and $last It's common when using ng-repeat to add specific behavior to the first or last element of the loop, e.g. special styling around the edges. Instead, ng-repeat already supplies you with two ready boolean properties. $first is true for the first element, and $last is true for the last element.
Angular-JS ng-repeat directive is a handy tool to repeat a set of HTML code for a number of times or once per item in a collection of items. ng-repeat is mostly used on arrays and objects.
It's hard to figure out what's the exact problem in your specific case, maybe it makes sense to provide an isolated example, so that other guys can help.
The result might depend on how you count the watchers. I took solution from here.
Here is a Plunker example working as expected (add or remove ::
in ng-repeat
):
HTML
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="[email protected]" data-semver="1.5.6" src="https://code.angularjs.org/1.5.6/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-controller="mainCtrl">
<div>{{name}}</div>
<ul>
<li ng-repeat="item in ::items">{{::item.id}} - {{::item.name}}</li>
</ul>
<button id="watchersCountBtn">Show watchers count</button>
<div id="watchersCountLog"></div>
</body>
</html>
JavaScript
angular
.module('app', [])
.controller('mainCtrl', function($scope) {
$scope.name = 'Hello World';
$scope.items = [
{ id: 1, name: 'product 1' },
{ id: 2, name: 'product 2' },
{ id: 3, name: 'product 3' },
{ id: 4, name: 'product 4' },
{ id: 5, name: 'product 5' },
{ id: 6, name: 'product 6' },
{ id: 7, name: 'product 7' },
{ id: 8, name: 'product 8' },
{ id: 9, name: 'product 9' },
{ id: 10, name: 'product 10' }
];
});
function getWatchers(root) {
root = angular.element(root || document.documentElement);
var watcherCount = 0;
function getElemWatchers(element) {
var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
var scopeWatchers = getWatchersFromScope(element.data().$scope);
var watchers = scopeWatchers.concat(isolateWatchers);
angular.forEach(element.children(), function (childElement) {
watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
});
return watchers;
}
function getWatchersFromScope(scope) {
if (scope) {
return scope.$$watchers || [];
} else {
return [];
}
}
return getElemWatchers(root);
}
window.onload = function() {
var btn = document.getElementById('watchersCountBtn');
var log = document.getElementById('watchersCountLog');
window.addEventListener('click', function() {
log.innerText = getWatchers().length;
});
};
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With