Ng - if called more times than it should

I am trying to filter out some channels depending on the selected category.

I have ng-repeat channel in channels , which has ng-if="hasCategory(channel.category)

Here's the doc:

 db.channels.find().pretty() { "_id" : "2kj9GK8jE9yHezoWb", "name" : "example name", "logo" : "path/to/image.svg", "number" : 2, "category" : [ "Broadcast", "Premium" ], "tags" : "example tag tags" } 

This is the function to handle ng-if:

 $scope.hasCategory = function (categoryNameArray) { console.log('thisisbeingcalled'); var e = _.indexOf(categoryNameArray, $scope.activeCategory); if (e === -1) { return false; } else { return true; } }; 

and this is how I set the active category:

 $scope.setCategory = function (name) { $scope.activeCategory = name; }; 

which I submit by clicking the button in the view:

 <section layout="row" layout-align="center center" layout-wrap ng-init="activeIndex; activeCategory"> <md-button flex="auto" flex-sm="45" flex-xs="100" ng-repeat="kit in kits | orderBy: 'order'" ng-class="{active: (activeIndex.index == $index)}" class="md-raised"> <a href="" ng-click="activeIndex.index = $index; setCategory(kit.name);" class="bold">{{kit.name}}</a> </md-button> </section> 

here is the document schema sets:

 db.kits.find().pretty() { "_id" : "k7JFX6DHu5GYnyer3", "name" : "Broadcast", "order" : 1 } { "_id" : "KrKRm4gysw5sfQnnr", "name" : "Premium", "order" : 2 } { "_id" : "dieukQ3NRsA44CSns", "name" : "Ultimate", "order" : 3 } 

Now I have only one channel to check this, but every time I press the button to change the category, the $scope.hasCategory function is called several times even when the page starts (first load)

enter image description here

I also have a search bar to search for channels in the current category, I'm not sure if this affects it either.

 <input type="text" ng-model="queryname" ng-model-options="{debounce: 500}"> 

Now it becomes very slow when I have more than 100 channels, ng-if receives a call more than 10k times, which silences the page for quite some time.

What can I do to fix this problem?

EDIT

Forgot to add where was ng-if :

 <md-card flex="15" flex-xs="40" class="slide-up" layout="column" ng-repeat="channel in channels | orderBy: 'number' | filter: queryname" ng-if="hasCategory(channel.category)" ng-init="channel.edit = false"> <md-card-header ng-show="channel.edit == false"> <img ng-src="{{channel.logo}}" alt=""> </md-card-header> <md-card-header-text ng-show="channel.edit == false"> <span class="md-subhead dark-blue" layout="row" layout-align="center" layout-margin>{{channel.number}}</span> </md-card-header-text> </md-card> 
+5
source share
1 answer

Your ng-if will be called in every digest cycle. The problem is that it contains an expression that includes a function call. Angular has no way of knowing when the result of an expression can change, so it calls it every time.

The best option would be to set a flag in each of the channels and use ng - if you just check the corresponding flag. Then you just need to update the flags whenever you change $scope.activeCategory you can either make with the code where you are setting the category, or using $scope.$watch() to run it automatically.

eg.

 $scope.setCategory = function (name) { $scope.activeCategory = name; for (var index=0; index < $scope.channels.length; index++) { $scope.channels[index].hasCategory = hasCategory($scope.channels[index].category, name); } }; function hasCategory(categoryNameArray, name) { console.log('thisisbeingcalled'); var e = _.indexOf(categoryNameArray, name); if (e === -1) { return false; } else { return true; } } 

Then in your template:

 <md-card flex="15" flex-xs="40" class="slide-up" layout="column" ng-repeat="channel in channels | orderBy: 'number' | filter: queryname" ng-if="channel.hasCategory" ng-init="channel.edit = false"> <md-card-header ng-show="channel.edit == false"> <img ng-src="{{channel.logo}}" alt=""> </md-card-header> <md-card-header-text ng-show="channel.edit == false"> <span class="md-subhead dark-blue" layout="row" layout-align="center" layout-margin>{{channel.number}}</span> </md-card-header-text> </md-card> 

should be more effective.

+6
source

Source: https://habr.com/ru/post/1241623/


All Articles