2016-01-27 10 views
5

Sto provando a filtrare alcuni canali in base alla categoria selezionata.ng-se viene chiamato più volte di quanto dovrebbe

Ho un ng-repeat di channel in channels che ha un ng-if="hasCategory(channel.category)

Ecco il documento:

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

Questa è la funzione per gestire il ng-se:

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

e questo è come ho impostato la categoria attiva:

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

che mando facendo clic sul pulsante nella vista:

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

ecco lo schema del kit documento:

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

Ora ho solo un canale per testare il tutto, ma ogni volta che cliccate il pulsante per cambiare categoria, la funzione $scope.hasCategory viene chiamata più volte anche all'avvio della pagina (caricamento iniziale)

enter image description here

Ho anche una barra di ricerca per cercare i canali nella categoria corrente, non sono sicuro se questo influisce anche su questo.

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

Ora questo diventa veramente lag quando ho più di 100 canali, il ng, se viene chiamato più di 10k volte, il che rende il congelamento pagina per un bel po '.

Cosa posso fare per risolvere questo problema?

EDIT

dimenticato di aggiungere dove il ng-if era:

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

risposta

6

tuo ng-if saranno chiamati in ogni ciclo digerire. Il problema è che contiene un'espressione che coinvolge una chiamata di funzione. Angolare non ha modo di sapere quando il risultato dell'espressione potrebbe cambiare, quindi lo chiama ogni volta.

Un'opzione migliore sarebbe quella di impostare un flag in ciascuno dei canali e utilizzare ng-if per testare il flag pertinente. Quindi devi semplicemente aggiornare i flag ogni volta che le modifiche sono $scope.activeCategory che puoi fare con il codice dove hai impostato la categoria o usando $scope.$watch() per attivarlo automaticamente.

ad es.

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

Poi nel modello:

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

dovrebbe essere più efficiente.

+0

ahh, grazie mille! Ho apportato alcune modifiche al tuo codice come '$ scope.channels [index].hasCategory = hasCategory ($ scope.channels [index] .category, name); 'e ora funziona, un'altra domanda è, come impostare la categoria di partenza in modo che l'utente non debba selezionare una categoria per visualizzare i canali . –

+0

nel metodo hasCategory(). Dovresti cambiare il valore di ritorno in 'return! (E === -1)'. È più leggibile – Riverside

+0

@Riverside, concordato che sarebbe un miglioramento, ma quando rispondo alle domande tento di mantenere le modifiche al codice dall'originale al minimo altrimenti c'è il rischio di oscurare le modifiche effettivamente necessarie per la risposta. – Duncan

Problemi correlati